mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 08:26:10 +00:00
requested changes
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
|
// Add a new column
|
||||||
|
t.string("new_id", 36).nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy data from old column to new column
|
||||||
|
await knex(TableName.SecretSharing).update({
|
||||||
|
// @ts-ignore
|
||||||
|
new_id: knex.raw("id::text")
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
|
// Make the new column not nullable
|
||||||
|
t.string("new_id", 36).notNullable().alter();
|
||||||
|
|
||||||
|
// Drop the old primary key
|
||||||
|
t.dropPrimary();
|
||||||
|
|
||||||
|
// Drop the old id column
|
||||||
|
t.dropColumn("id");
|
||||||
|
|
||||||
|
// Rename the new column to 'id'
|
||||||
|
t.renameColumn("new_id", "id");
|
||||||
|
|
||||||
|
// Set the new column as primary key
|
||||||
|
t.primary(["id"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
|
// Add a new UUID column
|
||||||
|
t.uuid("new_id").nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy data from string id to UUID, ensuring valid UUID format
|
||||||
|
await knex(TableName.SecretSharing).update({
|
||||||
|
// @ts-ignore
|
||||||
|
new_id: knex.raw("id::uuid")
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
|
// Make the new column not nullable
|
||||||
|
t.uuid("new_id").notNullable().alter();
|
||||||
|
|
||||||
|
// Drop the old primary key
|
||||||
|
t.dropPrimary();
|
||||||
|
|
||||||
|
// Drop the old id column
|
||||||
|
t.dropColumn("id");
|
||||||
|
|
||||||
|
// Rename the new column to 'id'
|
||||||
|
t.renameColumn("new_id", "id");
|
||||||
|
|
||||||
|
// Set the new column as primary key
|
||||||
|
t.primary(["id"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@ import { zodBuffer } from "@app/lib/zod";
|
|||||||
import { TImmutableDBKeys } from "./models";
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
export const SecretSharingSchema = z.object({
|
export const SecretSharingSchema = z.object({
|
||||||
id: z.string().uuid(),
|
|
||||||
encryptedValue: z.string().nullable().optional(),
|
encryptedValue: z.string().nullable().optional(),
|
||||||
iv: z.string().nullable().optional(),
|
iv: z.string().nullable().optional(),
|
||||||
tag: z.string().nullable().optional(),
|
tag: z.string().nullable().optional(),
|
||||||
@@ -25,7 +24,8 @@ export const SecretSharingSchema = z.object({
|
|||||||
name: z.string().nullable().optional(),
|
name: z.string().nullable().optional(),
|
||||||
lastViewedAt: z.date().nullable().optional(),
|
lastViewedAt: z.date().nullable().optional(),
|
||||||
password: z.string().nullable().optional(),
|
password: z.string().nullable().optional(),
|
||||||
encryptedSecret: zodBuffer.nullable().optional()
|
encryptedSecret: zodBuffer.nullable().optional(),
|
||||||
|
id: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretSharing = z.infer<typeof SecretSharingSchema>;
|
export type TSecretSharing = z.infer<typeof SecretSharingSchema>;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().uuid()
|
id: z.string()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
hashedHex: z.string().min(1),
|
hashedHex: z.string().min(1),
|
||||||
@@ -107,8 +107,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string()
|
||||||
hashedHex: z.string()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -117,7 +116,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
...req.body,
|
...req.body,
|
||||||
accessType: SecretSharingAccessType.Anyone
|
accessType: SecretSharingAccessType.Anyone
|
||||||
});
|
});
|
||||||
return { id: sharedSecret.id, hashedHex: sharedSecret.hashedHex };
|
return { id: sharedSecret.id };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -138,8 +137,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string()
|
||||||
hashedHex: z.string()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -153,7 +151,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
...req.body
|
...req.body
|
||||||
});
|
});
|
||||||
return { id: sharedSecret.id, hashedHex: sharedSecret.hashedHex };
|
return { id: sharedSecret.id };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -165,7 +163,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
sharedSecretId: z.string().uuid()
|
sharedSecretId: z.string()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: SecretSharingSchema
|
200: SecretSharingSchema
|
||||||
|
|||||||
@@ -82,11 +82,21 @@ export const secretSharingDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const create = async (data: Omit<TSecretSharing, "createdAt" | "updatedAt">, tx?: Knex) => {
|
||||||
|
try {
|
||||||
|
const [res] = await (tx || db)(TableName.SecretSharing).insert(data).returning("*");
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "Create Shared Secret" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...sharedSecretOrm,
|
...sharedSecretOrm,
|
||||||
countAllUserOrgSharedSecrets,
|
countAllUserOrgSharedSecrets,
|
||||||
pruneExpiredSharedSecrets,
|
pruneExpiredSharedSecrets,
|
||||||
softDeleteById,
|
softDeleteById,
|
||||||
findActiveSharedSecrets
|
findActiveSharedSecrets,
|
||||||
|
create
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -68,10 +68,15 @@ export const secretSharingServiceFactory = ({
|
|||||||
const encryptWithRoot = kmsService.encryptWithRootKey();
|
const encryptWithRoot = kmsService.encryptWithRootKey();
|
||||||
|
|
||||||
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
||||||
const hashedHex = crypto.createHash("sha256").update(secretValue).digest("hex").substring(0, 13);
|
|
||||||
|
// This will be 36 characters long, due to encoding it to base64.
|
||||||
|
const id = crypto.randomBytes(27).toString("base64url");
|
||||||
|
|
||||||
|
const hashedHex = crypto.createHash("sha256").update(id).digest("base64").substring(0, 13);
|
||||||
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
||||||
|
|
||||||
const newSharedSecret = await secretSharingDAL.create({
|
const newSharedSecret = await secretSharingDAL.create({
|
||||||
|
id,
|
||||||
iv: null,
|
iv: null,
|
||||||
tag: null,
|
tag: null,
|
||||||
encryptedValue: null,
|
encryptedValue: null,
|
||||||
@@ -86,7 +91,7 @@ export const secretSharingServiceFactory = ({
|
|||||||
accessType
|
accessType
|
||||||
});
|
});
|
||||||
|
|
||||||
return { id: newSharedSecret.id, hashedHex: newSharedSecret.hashedHex };
|
return { id: `${newSharedSecret.id}${hashedHex}` };
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPublicSharedSecret = async ({
|
const createPublicSharedSecret = async ({
|
||||||
@@ -116,10 +121,12 @@ export const secretSharingServiceFactory = ({
|
|||||||
const encryptWithRoot = kmsService.encryptWithRootKey();
|
const encryptWithRoot = kmsService.encryptWithRootKey();
|
||||||
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
||||||
|
|
||||||
const hashedHex = crypto.createHash("sha256").update(secretValue).digest("hex").substring(0, 13);
|
const id = crypto.randomBytes(27).toString("base64url");
|
||||||
|
const hashedHex = crypto.createHash("sha256").update(id).digest("hex").substring(0, 13);
|
||||||
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
||||||
|
|
||||||
const newSharedSecret = await secretSharingDAL.create({
|
const newSharedSecret = await secretSharingDAL.create({
|
||||||
|
id,
|
||||||
encryptedValue: null,
|
encryptedValue: null,
|
||||||
iv: null,
|
iv: null,
|
||||||
tag: null,
|
tag: null,
|
||||||
@@ -132,7 +139,7 @@ export const secretSharingServiceFactory = ({
|
|||||||
accessType
|
accessType
|
||||||
});
|
});
|
||||||
|
|
||||||
return { id: newSharedSecret.id, hashedHex: newSharedSecret.hashedHex };
|
return { id: `${newSharedSecret.id}${hashedHex}` };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSharedSecrets = async ({
|
const getSharedSecrets = async ({
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ export type TSharedSecret = {
|
|||||||
|
|
||||||
export type TCreatedSharedSecret = {
|
export type TCreatedSharedSecret = {
|
||||||
id: string;
|
id: string;
|
||||||
hashedHex: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TCreateSharedSecretRequest = {
|
export type TCreateSharedSecretRequest = {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export const ShareSecretForm = ({ isPublic, value }: Props) => {
|
|||||||
try {
|
try {
|
||||||
const expiresAt = new Date(new Date().getTime() + Number(expiresIn));
|
const expiresAt = new Date(new Date().getTime() + Number(expiresIn));
|
||||||
|
|
||||||
const { id, hashedHex } = await createSharedSecret.mutateAsync({
|
const { id } = await createSharedSecret.mutateAsync({
|
||||||
name,
|
name,
|
||||||
password,
|
password,
|
||||||
secretValue: secret,
|
secretValue: secret,
|
||||||
@@ -85,7 +85,7 @@ export const ShareSecretForm = ({ isPublic, value }: Props) => {
|
|||||||
accessType
|
accessType
|
||||||
});
|
});
|
||||||
|
|
||||||
setSecretLink(`${window.location.origin}/shared/secret/${id}-${hashedHex}`);
|
setSecretLink(`${window.location.origin}/shared/secret/${id}`);
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
setCopyTextSecret("secret");
|
setCopyTextSecret("secret");
|
||||||
|
|||||||
@@ -13,23 +13,33 @@ import { PasswordContainer, SecretContainer, SecretErrorContainer } from "./comp
|
|||||||
const extractDetailsFromUrl = (router: NextRouter) => {
|
const extractDetailsFromUrl = (router: NextRouter) => {
|
||||||
const { id, key: urlEncodedKey } = router.query;
|
const { id, key: urlEncodedKey } = router.query;
|
||||||
|
|
||||||
|
const idString = id as string;
|
||||||
|
|
||||||
|
if (!idString) {
|
||||||
|
return {
|
||||||
|
id: "",
|
||||||
|
hashedHex: "",
|
||||||
|
key: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (urlEncodedKey) {
|
if (urlEncodedKey) {
|
||||||
const [hashedHex, key] = urlEncodedKey ? urlEncodedKey.toString().split("-") : ["", ""];
|
const [hashedHex, key] = urlEncodedKey ? urlEncodedKey.toString().split("-") : ["", ""];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: id as string,
|
id: idString,
|
||||||
hashedHex,
|
hashedHex,
|
||||||
key
|
key
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// its like this {uuid}-{hex} so example: idpart1-idpart2-idpart3-idpart4-hex
|
// get the first 36 characters as id and the rest as hex
|
||||||
const extractedId = id?.toString().split("-").slice(0, 5).join("-");
|
const idPart = idString.substring(0, 36);
|
||||||
const extractedHex = id?.toString().split("-").slice(5).join("-");
|
const hexPart = idString.substring(36);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: extractedId || "",
|
id: idPart || "",
|
||||||
hashedHex: extractedHex || "",
|
hashedHex: hexPart || "",
|
||||||
key: null
|
key: null
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user