mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Begin frontend for blinded indices
This commit is contained in:
@@ -4,6 +4,8 @@ import {
|
||||
Secret
|
||||
} from '../../models';
|
||||
import crypto from 'crypto';
|
||||
import { SecretService } from '../../services';
|
||||
|
||||
|
||||
// TODO: modularize argon2id
|
||||
import * as argon2 from 'argon2';
|
||||
@@ -50,30 +52,47 @@ export const createSecret = async (req: Request, res: Response) => {
|
||||
workspaceId,
|
||||
environment,
|
||||
value,
|
||||
type
|
||||
type,
|
||||
secretKeyCiphertext,
|
||||
secretKeyIV,
|
||||
secretKeyTag,
|
||||
secretValueCiphertext,
|
||||
secretValueIV,
|
||||
secretValueTag
|
||||
} = req.body;
|
||||
|
||||
// use workspace salt
|
||||
const randomBytes = crypto.randomBytes(16);
|
||||
const secretBlindIndex = await SecretService.createSecretBlindIndex({
|
||||
secretName,
|
||||
workspaceId: new Types.ObjectId(workspaceId)
|
||||
});
|
||||
|
||||
// generate blind index
|
||||
// TODO 1: abstract away into create blind index function
|
||||
// TODO 2: create a get blind index function
|
||||
const secretBlindIndex = (await argon2.hash(secretName, {
|
||||
type: argon2.argon2id,
|
||||
salt: randomBytes,
|
||||
saltLength: 16, // default 16 bytes
|
||||
memoryCost: 65536, // default pool of 64 MiB per thread.
|
||||
hashLength: 32,
|
||||
parallelism: 1,
|
||||
raw: true
|
||||
})).toString('base64');
|
||||
// // use workspace salt
|
||||
// const randomBytes = crypto.randomBytes(16);
|
||||
|
||||
// // generate blind index
|
||||
// // TODO 1: abstract away into create blind index function
|
||||
// // TODO 2: create a get blind index function
|
||||
// const secretBlindIndex = (await argon2.hash(secretName, {
|
||||
// type: argon2.argon2id,
|
||||
// salt: randomBytes,
|
||||
// saltLength: 16, // default 16 bytes
|
||||
// memoryCost: 65536, // default pool of 64 MiB per thread.
|
||||
// hashLength: 32,
|
||||
// parallelism: 1,
|
||||
// raw: true
|
||||
// })).toString('base64');
|
||||
|
||||
// const secret = await new Secret({
|
||||
// workspace: new Types.ObjectId(workspaceId),
|
||||
// environment,
|
||||
// type,
|
||||
// secretBlindIndex
|
||||
// secretBlindIndex,
|
||||
// secretKeyCiphertext,
|
||||
// secretKeyIV,
|
||||
// secretKeyTag,
|
||||
// secretValueCiphertext,
|
||||
// secretValueIV,
|
||||
// secretValueTag
|
||||
// }).save();
|
||||
|
||||
return res.status(200).send({
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
ServiceTokenData,
|
||||
IServiceTokenData,
|
||||
Secret,
|
||||
ISecret
|
||||
ISecret,
|
||||
SecretBlindIndexData,
|
||||
} from '../models';
|
||||
import {
|
||||
validateMembership
|
||||
@@ -34,6 +35,9 @@ import {
|
||||
AUTH_MODE_SERVICE_TOKEN,
|
||||
AUTH_MODE_API_KEY
|
||||
} from '../variables';
|
||||
import crypto from 'crypto';
|
||||
import * as argon2 from 'argon2';
|
||||
|
||||
|
||||
/**
|
||||
* Validate authenticated clients for secrets with id [secretId] based
|
||||
@@ -192,7 +196,74 @@ const validateClientForSecrets = async ({
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return blind index for secret with
|
||||
* name [name] part of workspace with id [workspaceId]
|
||||
* @param {Object} obj
|
||||
* @param {Object} obj.secretName - name of secret to generate blind index for
|
||||
* @param {Object} obj.workspaceId - id of workspace that secret belongs to
|
||||
*/
|
||||
const createSecretBlindIndexHelper = async ({
|
||||
secretName,
|
||||
workspaceId
|
||||
}: {
|
||||
secretName: string;
|
||||
workspaceId: Types.ObjectId;
|
||||
}) => {
|
||||
|
||||
// check if workspace blind index data exists
|
||||
// const secretBlindIndexData = await SecretBlindIndexData.findOne({
|
||||
// workspace: workspaceId
|
||||
// });
|
||||
|
||||
// if (!secretBlindIndexData) {
|
||||
// // case: workspace blind index data has not been enabled
|
||||
// }
|
||||
|
||||
// TODO: randomBytes should come from the decrypted secretBlindIndexData
|
||||
const randomBytes = crypto.randomBytes(16);
|
||||
|
||||
const secretBlindIndex = (await argon2.hash(secretName, {
|
||||
type: argon2.argon2id,
|
||||
salt: randomBytes,
|
||||
saltLength: 16, // default 16 bytes
|
||||
memoryCost: 65536, // default pool of 64 MiB per thread.
|
||||
hashLength: 32,
|
||||
parallelism: 1,
|
||||
raw: true
|
||||
})).toString('base64');
|
||||
|
||||
return secretBlindIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the blind index for the secret with
|
||||
* name [name] part of workspace with id [workspaceId]
|
||||
* @param {Object} obj
|
||||
* @param {Object} obj.secretName - name of secret to generate blind index for
|
||||
* @param {Object} obj.workspaceId - id of workspace that secret belongs to
|
||||
*/
|
||||
const getSecretBlindIndexHelper = async ({
|
||||
secretName,
|
||||
workspaceId
|
||||
}: {
|
||||
secretName: string;
|
||||
workspaceId: Types.ObjectId;
|
||||
}) => {
|
||||
|
||||
// check if workspace blind index data exists
|
||||
const secretBlindIndexData = await SecretBlindIndexData.findOne({
|
||||
workspace: workspaceId
|
||||
});
|
||||
|
||||
if (!secretBlindIndexData) {
|
||||
// case: workspace blind index data has not been enabled
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
validateClientForSecret,
|
||||
validateClientForSecrets
|
||||
validateClientForSecrets,
|
||||
createSecretBlindIndexHelper,
|
||||
getSecretBlindIndexHelper
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
import { Schema, model, Types } from 'mongoose';
|
||||
import {
|
||||
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||
} from '../variables';
|
||||
|
||||
export interface IWorkspace {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
encryptionMode: string;
|
||||
organization: Types.ObjectId;
|
||||
environments: Array<{
|
||||
name: string;
|
||||
@@ -16,6 +22,15 @@ const workspaceSchema = new Schema<IWorkspace>({
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
encryptionMode: {
|
||||
type: String,
|
||||
default: 'e2ee',
|
||||
enum: [
|
||||
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||
]
|
||||
},
|
||||
autoCapitalization: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
// WIP
|
||||
import { Types } from 'mongoose';
|
||||
import {
|
||||
createSecretBlindIndexHelper,
|
||||
getSecretBlindIndexHelper
|
||||
} from '../helpers/secrets';
|
||||
|
||||
class SecretService {
|
||||
/**
|
||||
* Create and return blind index for secret with
|
||||
* name [name] part of workspace with id [workspaceId]
|
||||
* @param {Object} obj
|
||||
* @param {Object} obj.secretName - name of secret to generate blind index for
|
||||
* @param {Object} obj.workspaceId - id of workspace that secret belongs to
|
||||
*/
|
||||
static async createSecretBlindIndex({
|
||||
secretName,
|
||||
workspaceId,
|
||||
@@ -9,10 +20,19 @@ class SecretService {
|
||||
secretName: string;
|
||||
workspaceId: Types.ObjectId;
|
||||
}) {
|
||||
// TODO
|
||||
return;
|
||||
return await createSecretBlindIndexHelper({
|
||||
secretName,
|
||||
workspaceId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the blind index for the secret with
|
||||
* name [name] part of workspace with id [workspaceId]
|
||||
* @param {Object} obj
|
||||
* @param {Object} obj.secretName - name of secret to generate blind index for
|
||||
* @param {Object} obj.workspaceId - id of workspace that secret belongs to
|
||||
*/
|
||||
static async getSecretBlindIndex({
|
||||
secretName,
|
||||
workspaceId
|
||||
@@ -20,7 +40,11 @@ class SecretService {
|
||||
secretName: string;
|
||||
workspaceId: Types.ObjectId;
|
||||
}) {
|
||||
// TODO
|
||||
return;
|
||||
return await getSecretBlindIndexHelper({
|
||||
secretName,
|
||||
workspaceId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default SecretService;
|
||||
@@ -5,14 +5,14 @@ import BotService from './BotService';
|
||||
import EventService from './EventService';
|
||||
import IntegrationService from './IntegrationService';
|
||||
import TokenService from './TokenService';
|
||||
import SecretService from './SecretService';
|
||||
|
||||
export {
|
||||
TelemetryService,
|
||||
// logTelemetryMessage,
|
||||
// getPostHogClient,
|
||||
DatabaseService,
|
||||
BotService,
|
||||
EventService,
|
||||
IntegrationService,
|
||||
TokenService
|
||||
TokenService,
|
||||
SecretService
|
||||
}
|
||||
@@ -77,6 +77,11 @@ import {
|
||||
AUTH_MODE_SERVICE_TOKEN,
|
||||
AUTH_MODE_API_KEY
|
||||
} from './authentication';
|
||||
import {
|
||||
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||
} from './workspace';
|
||||
|
||||
export {
|
||||
OWNER,
|
||||
@@ -148,5 +153,8 @@ export {
|
||||
AUTH_MODE_JWT,
|
||||
AUTH_MODE_SERVICE_ACCOUNT,
|
||||
AUTH_MODE_SERVICE_TOKEN,
|
||||
AUTH_MODE_API_KEY
|
||||
AUTH_MODE_API_KEY,
|
||||
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||
};
|
||||
|
||||
9
backend/src/variables/workspace.ts
Normal file
9
backend/src/variables/workspace.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
const WORKSPACE_ENCRYPTION_MODE_E2EE = 'e2ee';
|
||||
const WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE = 'blind-indexed-e2ee';
|
||||
const WORKSPACE_ENCRYPTION_MODE_NOT_E2EE = 'not-e2ee';
|
||||
|
||||
export {
|
||||
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||
}
|
||||
@@ -39,9 +39,9 @@ import {
|
||||
CreateUpdateEnvFormData,
|
||||
CreateWsTag,
|
||||
EnvironmentSection,
|
||||
ProjectEncryptionModeSection,
|
||||
ProjectNameChangeSection,
|
||||
ServiceTokenSection
|
||||
} from './components';
|
||||
ServiceTokenSection} from './components';
|
||||
|
||||
export const ProjectSettingsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -349,6 +349,7 @@ export const ProjectSettingsPage = () => {
|
||||
workspaceAutoCapitalization={currentWorkspace?.autoCapitalization}
|
||||
onAutoCapitalizationChange={onAutoCapitalizationToggle}
|
||||
/>
|
||||
<ProjectEncryptionModeSection />
|
||||
<div className="mb-6 mt-4 flex w-full flex-col items-start rounded-md border-l border-red bg-white/5 px-6 pl-6 pb-4 pt-4">
|
||||
<p className="text-xl font-bold text-red">{t('settings-project:danger-zone')}</p>
|
||||
<p className="text-md mt-2 text-gray-400">{t('settings-project:danger-zone-note')}</p>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
export const ProjectEncryptionModeSection = () => {
|
||||
return (
|
||||
<div>
|
||||
Project encryption mode section
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { ProjectEncryptionModeSection } from './ProjectEncryptionModeSection';
|
||||
@@ -1,6 +1,7 @@
|
||||
export { CopyProjectIDSection } from './CopyProjectIDSection';
|
||||
export { EnvironmentSection } from './EnvironmentSection';
|
||||
export type { CreateUpdateEnvFormData } from './EnvironmentSection/EnvironmentSection';
|
||||
export { ProjectEncryptionModeSection } from './ProjectEncryptionModeSection';
|
||||
export { ProjectNameChangeSection } from './ProjectNameChangeSection';
|
||||
export type { CreateWsTag } from './SecretTagsSection/SecretTagsSection';
|
||||
export { ServiceTokenSection } from './ServiceTokenSection';
|
||||
|
||||
Reference in New Issue
Block a user