feat: generate ssh key

This commit is contained in:
Lorenzo Migliorero
2024-07-25 22:52:39 +02:00
parent 71555a15f8
commit a2eff67d44
3 changed files with 63 additions and 16 deletions

View File

@@ -42,6 +42,8 @@ export const AddSSHKey = ({ children }: Props) => {
const { mutateAsync, isError, error, isLoading } =
api.sshKey.create.useMutation();
const generateMutation = api.sshKey.generate.useMutation();
const form = useForm<SSHKey>({
resolver: zodResolver(sshKeyCreate),
});
@@ -71,8 +73,31 @@ export const AddSSHKey = ({ children }: Props) => {
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
<DialogHeader>
<DialogTitle>SSH Key</DialogTitle>
<DialogDescription>
In this section you can add an SSH key
<DialogDescription className="space-y-4">
<div>
In this section you can add one of your keys or generate a new
one.
</div>
<Button
variant={"secondary"}
isLoading={generateMutation.isLoading}
className="max-sm:w-full"
onClick={async () => {
await generateMutation
.mutateAsync()
.then(async (data) => {
toast.success("SSH Key Generated");
form.setValue("privateKey", data.privateKey);
form.setValue("publicKey", data.publicKey);
})
.catch(() => {
toast.error("Error to generate the SSH Key");
});
}}
type="button"
>
Generate SSH Key
</Button>
</DialogDescription>
</DialogHeader>
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}

View File

@@ -10,6 +10,7 @@ import {
apiRemoveSshKey,
apiUpdateSshKey,
} from "@/server/db/schema";
import { generateSSHKey } from "@/server/utils/filesystem/ssh";
import { TRPCError } from "@trpc/server";
import {
createSshKey,
@@ -49,6 +50,9 @@ export const sshRouter = createTRPCRouter({
all: adminProcedure.query(async () => {
return await db.query.sshKeys.findMany({});
}),
generate: protectedProcedure.mutation(async () => {
return await generateSSHKey();
}),
update: adminProcedure.input(apiUpdateSshKey).mutation(async ({ input }) => {
try {
return await updateSSHKeyById(input);

View File

@@ -3,6 +3,29 @@ import * as path from "node:path";
import { SSH_PATH } from "@/server/constants";
import { spawnAsync } from "../process/spawnAsync";
const readSSHKey = async (id: string) => {
try {
if (!fs.existsSync(SSH_PATH)) {
fs.mkdirSync(SSH_PATH, { recursive: true });
}
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(),
};
} catch (error) {
throw error;
}
};
export const saveSSHKey = async (
id: string,
publicKey: string,
@@ -24,21 +47,23 @@ export const saveSSHKey = async (
publicKeyStream.end();
};
export const generateSSHKey = async (id: string) => {
export const generateSSHKey = async () => {
const applicationDirectory = SSH_PATH;
if (!fs.existsSync(applicationDirectory)) {
fs.mkdirSync(applicationDirectory, { recursive: true });
}
const keyPath = path.join(applicationDirectory, `${id}_rsa`);
const keyPath = path.join(applicationDirectory, "temp_rsa");
if (fs.existsSync(`${keyPath}`)) {
fs.unlinkSync(`${keyPath}`);
}
if (fs.existsSync(`${keyPath}.pub`)) {
fs.unlinkSync(`${keyPath}.pub`);
}
const args = [
"-t",
"rsa",
@@ -46,25 +71,18 @@ export const generateSSHKey = async (id: string) => {
"4096",
"-C",
"dokploy",
"-m",
"PEM",
"-f",
keyPath,
"-N",
"",
];
try {
await spawnAsync("ssh-keygen", args);
return keyPath;
} catch (error) {
throw error;
}
};
export const readSSHPublicKey = async (id: string) => {
try {
if (!fs.existsSync(SSH_PATH)) {
fs.mkdirSync(SSH_PATH, { recursive: true });
}
const keyPath = path.join(SSH_PATH, `${id}_rsa.pub`);
const data = fs.readFileSync(keyPath, { encoding: "utf-8" });
const data = await readSSHKey("temp");
await removeSSHKey("temp");
return data;
} catch (error) {
throw error;