feat: ssh key type and whitespaces

This commit is contained in:
Lorenzo Migliorero
2024-07-25 23:32:52 +02:00
parent 12bd017d07
commit 2724336cad
6 changed files with 94 additions and 49 deletions

View File

@@ -7,6 +7,7 @@ import { db } from "@/server/db";
import {
apiCreateSshKey,
apiFindOneSshKey,
apiGenerateSSHKey,
apiRemoveSshKey,
apiUpdateSshKey,
} from "@/server/db/schema";
@@ -50,9 +51,11 @@ export const sshRouter = createTRPCRouter({
all: adminProcedure.query(async () => {
return await db.query.sshKeys.findMany({});
}),
generate: protectedProcedure.mutation(async () => {
return await generateSSHKey();
}),
generate: protectedProcedure
.input(apiGenerateSSHKey)
.mutation(async ({ input }) => {
return await generateSSHKey(input);
}),
update: adminProcedure.input(apiUpdateSshKey).mutation(async ({ input }) => {
try {
return await updateSSHKeyById(input);

View File

@@ -1,6 +1,6 @@
import { applications } from "@/server/db/schema/application";
import { compose } from "@/server/db/schema/compose";
import { sshKeyCreate } from "@/server/db/validations";
import { sshKeyCreate, sshKeyType } from "@/server/db/validations";
import { relations } from "drizzle-orm";
import { pgTable, text, time } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
@@ -45,6 +45,8 @@ export const apiFindOneSshKey = createSchema
})
.required();
export const apiGenerateSSHKey = sshKeyType;
export const apiRemoveSshKey = createSchema
.pick({
sshKeyId: true,

View File

@@ -3,20 +3,33 @@ import { z } from "zod";
export const sshKeyCreate = z.object({
name: z.string().min(1),
description: z.string().optional(),
publicKey: z.string().regex(/^ssh-rsa\s+([A-Za-z0-9+/=]+)\s*(.*)?$/, {
message: "Invalid format",
}),
privateKey: z
.string()
.regex(
/^-----BEGIN RSA PRIVATE KEY-----\n([A-Za-z0-9+/=\n]+)-----END RSA PRIVATE KEY-----$/,
{
message: "Invalid format",
},
),
publicKey: z.string().refine(
(key) => {
const rsaPubPattern = /^ssh-rsa\s+([A-Za-z0-9+/=]+)\s*(.*)?\s*$/;
const ed25519PubPattern = /^ssh-ed25519\s+([A-Za-z0-9+/=]+)\s*(.*)?\s*$/;
return rsaPubPattern.test(key) || ed25519PubPattern.test(key);
},
{
message: "Invalid public key format",
},
),
privateKey: z.string().refine(
(key) => {
const rsaPrivPattern =
/^-----BEGIN RSA PRIVATE KEY-----\n([A-Za-z0-9+/=\n]+)-----END RSA PRIVATE KEY-----\s*$/;
const ed25519PrivPattern =
/^-----BEGIN OPENSSH PRIVATE KEY-----\n([A-Za-z0-9+/=\n]+)-----END OPENSSH PRIVATE KEY-----\s*$/;
return rsaPrivPattern.test(key) || ed25519PrivPattern.test(key);
},
{
message: "Invalid private key format",
},
),
});
export const sshKeyUpdate = sshKeyCreate.pick({
name: true,
description: true,
});
export const sshKeyType = z.enum(["rsa", "ed25519"]).optional();

View File

@@ -10,16 +10,12 @@ const readSSHKey = async (id: string) => {
}
return {
privateKey: fs
.readFileSync(path.join(SSH_PATH, `${id}_rsa`), {
encoding: "utf-8",
})
.trim(),
publicKey: fs
.readFileSync(path.join(SSH_PATH, `${id}_rsa.pub`), {
encoding: "utf-8",
})
.trim(),
privateKey: fs.readFileSync(path.join(SSH_PATH, `${id}_rsa`), {
encoding: "utf-8",
}),
publicKey: fs.readFileSync(path.join(SSH_PATH, `${id}_rsa.pub`), {
encoding: "utf-8",
}),
};
} catch (error) {
throw error;
@@ -47,7 +43,7 @@ export const saveSSHKey = async (
publicKeyStream.end();
};
export const generateSSHKey = async () => {
export const generateSSHKey = async (type: "rsa" | "ed25519" = "rsa") => {
const applicationDirectory = SSH_PATH;
if (!fs.existsSync(applicationDirectory)) {
@@ -66,7 +62,7 @@ export const generateSSHKey = async () => {
const args = [
"-t",
"rsa",
type,
"-b",
"4096",
"-C",