mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 10:28:22 +00:00
Begin frontend for blinded indices
This commit is contained in:
@@ -4,6 +4,8 @@ import {
|
|||||||
Secret
|
Secret
|
||||||
} from '../../models';
|
} from '../../models';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
import { SecretService } from '../../services';
|
||||||
|
|
||||||
|
|
||||||
// TODO: modularize argon2id
|
// TODO: modularize argon2id
|
||||||
import * as argon2 from 'argon2';
|
import * as argon2 from 'argon2';
|
||||||
@@ -50,30 +52,47 @@ export const createSecret = async (req: Request, res: Response) => {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
environment,
|
environment,
|
||||||
value,
|
value,
|
||||||
type
|
type,
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
// use workspace salt
|
const secretBlindIndex = await SecretService.createSecretBlindIndex({
|
||||||
const randomBytes = crypto.randomBytes(16);
|
secretName,
|
||||||
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
// generate blind index
|
// // use workspace salt
|
||||||
// TODO 1: abstract away into create blind index function
|
// const randomBytes = crypto.randomBytes(16);
|
||||||
// TODO 2: create a get blind index function
|
|
||||||
const secretBlindIndex = (await argon2.hash(secretName, {
|
// // generate blind index
|
||||||
type: argon2.argon2id,
|
// // TODO 1: abstract away into create blind index function
|
||||||
salt: randomBytes,
|
// // TODO 2: create a get blind index function
|
||||||
saltLength: 16, // default 16 bytes
|
// const secretBlindIndex = (await argon2.hash(secretName, {
|
||||||
memoryCost: 65536, // default pool of 64 MiB per thread.
|
// type: argon2.argon2id,
|
||||||
hashLength: 32,
|
// salt: randomBytes,
|
||||||
parallelism: 1,
|
// saltLength: 16, // default 16 bytes
|
||||||
raw: true
|
// memoryCost: 65536, // default pool of 64 MiB per thread.
|
||||||
})).toString('base64');
|
// hashLength: 32,
|
||||||
|
// parallelism: 1,
|
||||||
|
// raw: true
|
||||||
|
// })).toString('base64');
|
||||||
|
|
||||||
// const secret = await new Secret({
|
// const secret = await new Secret({
|
||||||
// workspace: new Types.ObjectId(workspaceId),
|
// workspace: new Types.ObjectId(workspaceId),
|
||||||
// environment,
|
// environment,
|
||||||
// type,
|
// type,
|
||||||
// secretBlindIndex
|
// secretBlindIndex,
|
||||||
|
// secretKeyCiphertext,
|
||||||
|
// secretKeyIV,
|
||||||
|
// secretKeyTag,
|
||||||
|
// secretValueCiphertext,
|
||||||
|
// secretValueIV,
|
||||||
|
// secretValueTag
|
||||||
// }).save();
|
// }).save();
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import {
|
|||||||
ServiceTokenData,
|
ServiceTokenData,
|
||||||
IServiceTokenData,
|
IServiceTokenData,
|
||||||
Secret,
|
Secret,
|
||||||
ISecret
|
ISecret,
|
||||||
|
SecretBlindIndexData,
|
||||||
} from '../models';
|
} from '../models';
|
||||||
import {
|
import {
|
||||||
validateMembership
|
validateMembership
|
||||||
@@ -34,6 +35,9 @@ import {
|
|||||||
AUTH_MODE_SERVICE_TOKEN,
|
AUTH_MODE_SERVICE_TOKEN,
|
||||||
AUTH_MODE_API_KEY
|
AUTH_MODE_API_KEY
|
||||||
} from '../variables';
|
} from '../variables';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import * as argon2 from 'argon2';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate authenticated clients for secrets with id [secretId] based
|
* 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 {
|
export {
|
||||||
validateClientForSecret,
|
validateClientForSecret,
|
||||||
validateClientForSecrets
|
validateClientForSecrets,
|
||||||
|
createSecretBlindIndexHelper,
|
||||||
|
getSecretBlindIndexHelper
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,14 @@
|
|||||||
import { Schema, model, Types } from 'mongoose';
|
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 {
|
export interface IWorkspace {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
name: string;
|
name: string;
|
||||||
|
encryptionMode: string;
|
||||||
organization: Types.ObjectId;
|
organization: Types.ObjectId;
|
||||||
environments: Array<{
|
environments: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
@@ -16,6 +22,15 @@ const workspaceSchema = new Schema<IWorkspace>({
|
|||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
encryptionMode: {
|
||||||
|
type: String,
|
||||||
|
default: 'e2ee',
|
||||||
|
enum: [
|
||||||
|
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||||
|
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||||
|
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||||
|
]
|
||||||
|
},
|
||||||
autoCapitalization: {
|
autoCapitalization: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
// WIP
|
// WIP
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
|
import {
|
||||||
|
createSecretBlindIndexHelper,
|
||||||
|
getSecretBlindIndexHelper
|
||||||
|
} from '../helpers/secrets';
|
||||||
|
|
||||||
class SecretService {
|
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({
|
static async createSecretBlindIndex({
|
||||||
secretName,
|
secretName,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@@ -9,10 +20,19 @@ class SecretService {
|
|||||||
secretName: string;
|
secretName: string;
|
||||||
workspaceId: Types.ObjectId;
|
workspaceId: Types.ObjectId;
|
||||||
}) {
|
}) {
|
||||||
// TODO
|
return await createSecretBlindIndexHelper({
|
||||||
return;
|
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({
|
static async getSecretBlindIndex({
|
||||||
secretName,
|
secretName,
|
||||||
workspaceId
|
workspaceId
|
||||||
@@ -20,7 +40,11 @@ class SecretService {
|
|||||||
secretName: string;
|
secretName: string;
|
||||||
workspaceId: Types.ObjectId;
|
workspaceId: Types.ObjectId;
|
||||||
}) {
|
}) {
|
||||||
// TODO
|
return await getSecretBlindIndexHelper({
|
||||||
return;
|
secretName,
|
||||||
|
workspaceId
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default SecretService;
|
||||||
@@ -5,14 +5,14 @@ import BotService from './BotService';
|
|||||||
import EventService from './EventService';
|
import EventService from './EventService';
|
||||||
import IntegrationService from './IntegrationService';
|
import IntegrationService from './IntegrationService';
|
||||||
import TokenService from './TokenService';
|
import TokenService from './TokenService';
|
||||||
|
import SecretService from './SecretService';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
TelemetryService,
|
TelemetryService,
|
||||||
// logTelemetryMessage,
|
|
||||||
// getPostHogClient,
|
|
||||||
DatabaseService,
|
DatabaseService,
|
||||||
BotService,
|
BotService,
|
||||||
EventService,
|
EventService,
|
||||||
IntegrationService,
|
IntegrationService,
|
||||||
TokenService
|
TokenService,
|
||||||
|
SecretService
|
||||||
}
|
}
|
||||||
@@ -77,6 +77,11 @@ import {
|
|||||||
AUTH_MODE_SERVICE_TOKEN,
|
AUTH_MODE_SERVICE_TOKEN,
|
||||||
AUTH_MODE_API_KEY
|
AUTH_MODE_API_KEY
|
||||||
} from './authentication';
|
} from './authentication';
|
||||||
|
import {
|
||||||
|
WORKSPACE_ENCRYPTION_MODE_E2EE,
|
||||||
|
WORKSPACE_ENCRYPTION_MODE_BLIND_INDEXED_E2EE,
|
||||||
|
WORKSPACE_ENCRYPTION_MODE_NOT_E2EE
|
||||||
|
} from './workspace';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
OWNER,
|
OWNER,
|
||||||
@@ -148,5 +153,8 @@ export {
|
|||||||
AUTH_MODE_JWT,
|
AUTH_MODE_JWT,
|
||||||
AUTH_MODE_SERVICE_ACCOUNT,
|
AUTH_MODE_SERVICE_ACCOUNT,
|
||||||
AUTH_MODE_SERVICE_TOKEN,
|
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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,
|
CreateUpdateEnvFormData,
|
||||||
CreateWsTag,
|
CreateWsTag,
|
||||||
EnvironmentSection,
|
EnvironmentSection,
|
||||||
|
ProjectEncryptionModeSection,
|
||||||
ProjectNameChangeSection,
|
ProjectNameChangeSection,
|
||||||
ServiceTokenSection
|
ServiceTokenSection} from './components';
|
||||||
} from './components';
|
|
||||||
|
|
||||||
export const ProjectSettingsPage = () => {
|
export const ProjectSettingsPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -349,6 +349,7 @@ export const ProjectSettingsPage = () => {
|
|||||||
workspaceAutoCapitalization={currentWorkspace?.autoCapitalization}
|
workspaceAutoCapitalization={currentWorkspace?.autoCapitalization}
|
||||||
onAutoCapitalizationChange={onAutoCapitalizationToggle}
|
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">
|
<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-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>
|
<p className="text-md mt-2 text-gray-400">{t('settings-project:danger-zone-note')}</p>
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
export const ProjectEncryptionModeSection = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Project encryption mode section
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
export { ProjectEncryptionModeSection } from './ProjectEncryptionModeSection';
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export { CopyProjectIDSection } from './CopyProjectIDSection';
|
export { CopyProjectIDSection } from './CopyProjectIDSection';
|
||||||
export { EnvironmentSection } from './EnvironmentSection';
|
export { EnvironmentSection } from './EnvironmentSection';
|
||||||
export type { CreateUpdateEnvFormData } from './EnvironmentSection/EnvironmentSection';
|
export type { CreateUpdateEnvFormData } from './EnvironmentSection/EnvironmentSection';
|
||||||
|
export { ProjectEncryptionModeSection } from './ProjectEncryptionModeSection';
|
||||||
export { ProjectNameChangeSection } from './ProjectNameChangeSection';
|
export { ProjectNameChangeSection } from './ProjectNameChangeSection';
|
||||||
export type { CreateWsTag } from './SecretTagsSection/SecretTagsSection';
|
export type { CreateWsTag } from './SecretTagsSection/SecretTagsSection';
|
||||||
export { ServiceTokenSection } from './ServiceTokenSection';
|
export { ServiceTokenSection } from './ServiceTokenSection';
|
||||||
|
|||||||
Reference in New Issue
Block a user