feat(e2e): fixed seed file issue and added more seeding

This commit is contained in:
Akhil Mohan
2024-02-15 20:25:39 +05:30
parent 1855fc769d
commit f09c48d79b
14 changed files with 338 additions and 101 deletions
+4
View File
@@ -10,6 +10,10 @@ dotenv.config({
path: path.join(__dirname, "../../../.env.migration"),
debug: true
});
dotenv.config({
path: path.join(__dirname, "../../../.env"),
debug: true
});
export default {
development: {
client: "postgres",
+97 -18
View File
@@ -6,13 +6,14 @@ import nacl from "tweetnacl";
import { encodeBase64 } from "tweetnacl-util";
import {
decryptAsymmetric,
// decryptAsymmetric,
decryptSymmetric,
decryptSymmetric128BitHexKeyUTF8,
encryptAsymmetric,
encryptSymmetric
encryptSymmetric128BitHexKeyUTF8
} from "@app/lib/crypto";
import { TUserEncryptionKeys } from "./schemas";
import { TSecrets, TUserEncryptionKeys } from "./schemas";
export const seedData1 = {
id: "3dafd81d-4388-432b-a4c5-f735616868c1",
@@ -31,6 +32,14 @@ export const seedData1 = {
name: "Development",
slug: "dev"
},
machineIdentity: {
id: "88fa7aed-9288-401e-a4c9-fa9430be62a0",
name: "mac1",
clientCred: {
id: "3f6135db-f237-421d-af66-a8f4e80d443b",
secret: "da35a5a5a7b57f977a9a73394506e878a7175d06606df43dc93e1472b10cf339"
}
},
token: {
id: "a9dfafba-a3b7-42e3-8618-91abb702fd36"
}
@@ -73,7 +82,7 @@ export const generateUserSrpKeys = async (password: string) => {
ciphertext: encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag
} = encryptSymmetric(privateKey, key.toString("base64"));
} = encryptSymmetric128BitHexKeyUTF8(privateKey, key);
// create the protected key by encrypting the symmetric key
// [key] with the derived key
@@ -81,7 +90,7 @@ export const generateUserSrpKeys = async (password: string) => {
ciphertext: protectedKey,
iv: protectedKeyIV,
tag: protectedKeyTag
} = encryptSymmetric(key.toString("hex"), derivedKey.toString("base64"));
} = encryptSymmetric128BitHexKeyUTF8(key.toString("hex"), derivedKey);
return {
protectedKey,
@@ -107,32 +116,102 @@ export const getUserPrivateKey = async (password: string, user: TUserEncryptionK
raw: true
});
if (!derivedKey) throw new Error("Failed to derive key from password");
const key = decryptSymmetric({
const key = decryptSymmetric128BitHexKeyUTF8({
ciphertext: user.protectedKey as string,
iv: user.protectedKeyIV as string,
tag: user.protectedKeyTag as string,
key: derivedKey.toString("base64")
key: derivedKey
});
const privateKey = decryptSymmetric({
const privateKey = decryptSymmetric128BitHexKeyUTF8({
ciphertext: user.encryptedPrivateKey,
iv: user.iv,
tag: user.tag,
key
key: Buffer.from(key, "hex")
});
return privateKey;
};
export const buildUserProjectKey = async (privateKey: string, publickey: string) => {
export const buildUserProjectKey = (privateKey: string, publickey: string) => {
const randomBytes = crypto.randomBytes(16).toString("hex");
const { nonce, ciphertext } = encryptAsymmetric(randomBytes, publickey, privateKey);
return { nonce, ciphertext };
};
// export const getUserProjectKey = async (privateKey: string) => {
// const key = decryptAsymmetric({
// ciphertext: decryptFileKey.encryptedKey,
// nonce: decryptFileKey.nonce,
// publicKey: decryptFileKey.sender.publicKey,
// privateKey: PRIVATE_KEY
// });
// };
export const getUserProjectKey = async (privateKey: string, ciphertext: string, nonce: string, publicKey: string) => {
return decryptAsymmetric({
ciphertext,
nonce,
publicKey,
privateKey
});
};
export const encryptSecret = (encKey: string, key: string, value?: string, comment?: string) => {
// encrypt key
const {
ciphertext: secretKeyCiphertext,
iv: secretKeyIV,
tag: secretKeyTag
} = encryptSymmetric128BitHexKeyUTF8(key, encKey);
// encrypt value
const {
ciphertext: secretValueCiphertext,
iv: secretValueIV,
tag: secretValueTag
} = encryptSymmetric128BitHexKeyUTF8(value ?? "", encKey);
// encrypt comment
const {
ciphertext: secretCommentCiphertext,
iv: secretCommentIV,
tag: secretCommentTag
} = encryptSymmetric128BitHexKeyUTF8(comment ?? "", encKey);
return {
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag
};
};
export const decryptSecret = (decryptKey: string, encSecret: TSecrets) => {
const secretKey = decryptSymmetric128BitHexKeyUTF8({
key: decryptKey,
ciphertext: encSecret.secretKeyCiphertext,
tag: encSecret.secretKeyTag,
iv: encSecret.secretKeyIV
});
const secretValue = decryptSymmetric128BitHexKeyUTF8({
key: decryptKey,
ciphertext: encSecret.secretValueCiphertext,
tag: encSecret.secretValueTag,
iv: encSecret.secretValueIV
});
const secretComment =
encSecret.secretCommentIV && encSecret.secretCommentTag && encSecret.secretCommentCiphertext
? decryptSymmetric128BitHexKeyUTF8({
key: decryptKey,
ciphertext: encSecret.secretCommentCiphertext,
tag: encSecret.secretCommentTag,
iv: encSecret.secretCommentIV
})
: null;
return {
key: secretKey,
value: secretValue,
comment: secretComment,
version: encSecret.version
};
};
+4 -2
View File
@@ -14,7 +14,8 @@ export async function seed(knex: Knex): Promise<void> {
const [user] = await knex(TableName.Users)
.insert([
{
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
// eslint-disable-next-line
// @ts-ignore
id: seedData1.id,
email: seedData1.email,
superAdmin: true,
@@ -48,7 +49,8 @@ export async function seed(knex: Knex): Promise<void> {
]);
await knex(TableName.AuthTokenSession).insert({
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
// eslint-disable-next-line
// @ts-ignore
id: seedData1.token.id,
userId: seedData1.id,
ip: "151.196.220.213",
+2 -1
View File
@@ -14,7 +14,8 @@ export async function seed(knex: Knex): Promise<void> {
const [org] = await knex(TableName.Organization)
.insert([
{
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
// eslint-disable-next-line
// @ts-ignore
id: seedData1.organization.id,
name: "infisical",
slug: "infisical",
+38 -8
View File
@@ -1,7 +1,11 @@
import crypto from "node:crypto";
import { Knex } from "knex";
import { OrgMembershipRole, TableName } from "../schemas";
import { seedData1 } from "../seed-data";
import { encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
import { OrgMembershipRole, SecretEncryptionAlgo, SecretKeyEncoding, TableName } from "../schemas";
import { buildUserProjectKey, getUserPrivateKey, seedData1 } from "../seed-data";
export const DEFAULT_PROJECT_ENVS = [
{ name: "Development", slug: "dev" },
@@ -20,21 +24,32 @@ export async function seed(knex: Knex): Promise<void> {
name: seedData1.project.name,
orgId: seedData1.organization.id,
slug: "first-project",
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
// eslint-disable-next-line
// @ts-ignore
id: seedData1.project.id
})
.returning("*");
// await knex(TableName.ProjectKeys).insert({
// projectId: project.id,
// senderId: seedData1.id
// });
await knex(TableName.ProjectMembership).insert({
projectId: project.id,
role: OrgMembershipRole.Admin,
userId: seedData1.id
});
const user = await knex(TableName.UserEncryptionKey).where({ userId: seedData1.id }).first();
if (!user) throw new Error("User not found");
const userPrivateKey = await getUserPrivateKey(seedData1.password, user);
const projectKey = buildUserProjectKey(userPrivateKey, user.publicKey);
await knex(TableName.ProjectKeys).insert({
projectId: project.id,
nonce: projectKey.nonce,
encryptedKey: projectKey.ciphertext,
receiverId: seedData1.id,
senderId: seedData1.id
});
// create default environments and default folders
const envs = await knex(TableName.Environment)
.insert(
DEFAULT_PROJECT_ENVS.map(({ name, slug }, index) => ({
@@ -46,4 +61,19 @@ export async function seed(knex: Knex): Promise<void> {
)
.returning("*");
await knex(TableName.SecretFolder).insert(envs.map(({ id }) => ({ name: "root", envId: id, parentId: null })));
// save secret secret blind index
const encKey = process.env.ENCRYPTION_KEY;
if (!encKey) throw new Error("Missing ENCRYPTION_KEY");
const salt = crypto.randomBytes(16).toString("base64");
const secretBlindIndex = encryptSymmetric128BitHexKeyUTF8(salt, encKey);
// insert secret blind index for project
await knex(TableName.SecretBlindIndex).insert({
projectId: project.id,
encryptedSaltCipherText: secretBlindIndex.ciphertext,
saltIV: secretBlindIndex.iv,
saltTag: secretBlindIndex.tag,
algorithm: SecretEncryptionAlgo.AES_256_GCM,
keyEncoding: SecretKeyEncoding.UTF8
});
}
@@ -0,0 +1,83 @@
import bcrypt from "bcrypt";
import { Knex } from "knex";
import { IdentityAuthMethod, OrgMembershipRole, ProjectMembershipRole, TableName } from "../schemas";
import { seedData1 } from "../seed-data";
export async function seed(knex: Knex): Promise<void> {
// Deletes ALL existing entries
await knex(TableName.Identity).del();
await knex(TableName.IdentityOrgMembership).del();
// Inserts seed entries
await knex(TableName.Identity).insert([
{
// eslint-disable-next-line
// @ts-ignore
id: seedData1.machineIdentity.id,
name: seedData1.machineIdentity.name,
authMethod: IdentityAuthMethod.Univeral
}
]);
const identityUa = await knex(TableName.IdentityUniversalAuth)
.insert([
{
identityId: seedData1.machineIdentity.id,
clientId: seedData1.machineIdentity.clientCred.id,
clientSecretTrustedIps: JSON.stringify([
{
type: "ipv4",
prefix: 0,
ipAddress: "0.0.0.0"
},
{
type: "ipv6",
prefix: 0,
ipAddress: "::"
}
]),
accessTokenTrustedIps: JSON.stringify([
{
type: "ipv4",
prefix: 0,
ipAddress: "0.0.0.0"
},
{
type: "ipv6",
prefix: 0,
ipAddress: "::"
}
]),
accessTokenTTL: 2592000,
accessTokenMaxTTL: 2592000,
accessTokenNumUsesLimit: 0
}
])
.returning("*");
const clientSecretHash = await bcrypt.hash(seedData1.machineIdentity.clientCred.secret, 10);
await knex(TableName.IdentityUaClientSecret).insert([
{
identityUAId: identityUa[0].id,
description: "",
clientSecretTTL: 0,
clientSecretNumUses: 0,
clientSecretNumUsesLimit: 0,
clientSecretPrefix: seedData1.machineIdentity.clientCred.secret.slice(0, 4),
clientSecretHash,
isClientSecretRevoked: false
}
]);
await knex(TableName.IdentityOrgMembership).insert([
{
identityId: seedData1.machineIdentity.id,
orgId: seedData1.organization.id,
role: OrgMembershipRole.Admin
}
]);
await knex(TableName.IdentityProjectMembership).insert({
identityId: seedData1.machineIdentity.id,
role: ProjectMembershipRole.Admin,
projectId: seedData1.project.id
});
}