fix: rde local ports
This commit is contained in:
parent
424195880b
commit
76d134fcda
@ -476,9 +476,28 @@ export const supportedDatabaseTypesAndVersions = [
|
|||||||
},
|
},
|
||||||
{ name: 'couchdb', fancyName: 'CouchDB', baseImage: 'bitnami/couchdb', versions: ['3.2.2'] }
|
{ name: 'couchdb', fancyName: 'CouchDB', baseImage: 'bitnami/couchdb', versions: ['3.2.2'] }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export async function getFreeSSHLocalPort(id: string): Promise<number> {
|
||||||
|
const { default: getPort, portNumbers } = await import('get-port');
|
||||||
|
const { remoteIpAddress, sshLocalPort } = await prisma.destinationDocker.findUnique({ where: { id } })
|
||||||
|
if (sshLocalPort) {
|
||||||
|
return Number(sshLocalPort)
|
||||||
|
}
|
||||||
|
const ports = await prisma.destinationDocker.findMany({ where: { sshLocalPort: { not: null }, remoteIpAddress: { not: remoteIpAddress } } })
|
||||||
|
const alreadyConfigured = await prisma.destinationDocker.findFirst({ where: { remoteIpAddress, id: { not: id }, sshLocalPort: { not: null } } })
|
||||||
|
if (alreadyConfigured?.sshLocalPort) {
|
||||||
|
await prisma.destinationDocker.update({ where: { id }, data: { sshLocalPort: alreadyConfigured.sshLocalPort } })
|
||||||
|
return Number(alreadyConfigured.sshLocalPort)
|
||||||
|
}
|
||||||
|
const availablePort = await getPort({ port: portNumbers(10000, 10100), exclude: ports.map(p => p.sshLocalPort) })
|
||||||
|
await prisma.destinationDocker.update({ where: { id }, data: { sshLocalPort: Number(availablePort) } })
|
||||||
|
return Number(availablePort)
|
||||||
|
}
|
||||||
|
|
||||||
export async function createRemoteEngineConfiguration(id: string) {
|
export async function createRemoteEngineConfiguration(id: string) {
|
||||||
const homedir = os.homedir();
|
const homedir = os.homedir();
|
||||||
const sshKeyFile = `/tmp/id_rsa-${id}`
|
const sshKeyFile = `/tmp/id_rsa-${id}`
|
||||||
|
const localPort = await getFreeSSHLocalPort(id);
|
||||||
const { sshKey: { privateKey }, remoteIpAddress, remotePort, remoteUser } = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } })
|
const { sshKey: { privateKey }, remoteIpAddress, remotePort, remoteUser } = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } })
|
||||||
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 })
|
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 })
|
||||||
// Needed for remote docker compose
|
// Needed for remote docker compose
|
||||||
@ -488,24 +507,23 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
}
|
}
|
||||||
await asyncExecShell(`SSH_AUTH_SOCK=/tmp/ssh-agent.pid ssh-add -q ${sshKeyFile}`)
|
await asyncExecShell(`SSH_AUTH_SOCK=/tmp/ssh-agent.pid ssh-add -q ${sshKeyFile}`)
|
||||||
|
|
||||||
const { stdout: numberOfSSHTunnelsRunning } = await asyncExecShell(`ps ax | grep 'ssh -o StrictHostKeyChecking no -fNL 11122:localhost:${remotePort}' | grep -v grep | wc -l`)
|
const { stdout: numberOfSSHTunnelsRunning } = await asyncExecShell(`ps ax | grep 'ssh -F /dev/null -o StrictHostKeyChecking no -fNL ${localPort}:localhost:${remotePort}' | grep -v grep | wc -l`)
|
||||||
if (numberOfSSHTunnelsRunning !== '' && Number(numberOfSSHTunnelsRunning.trim()) == 0) {
|
if (numberOfSSHTunnelsRunning !== '' && Number(numberOfSSHTunnelsRunning.trim()) == 0) {
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`SSH_AUTH_SOCK=/tmp/ssh-agent.pid ssh -o "StrictHostKeyChecking no" -fNL 11122:localhost:${remotePort} ${remoteUser}@${remoteIpAddress}`)
|
await asyncExecShell(`SSH_AUTH_SOCK=/tmp/ssh-agent.pid ssh -F /dev/null -o "StrictHostKeyChecking no" -fNL ${localPort}:localhost:${remotePort} ${remoteUser}@${remoteIpAddress}`)
|
||||||
|
|
||||||
} catch(error){
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = sshConfig.parse('')
|
const config = sshConfig.parse('')
|
||||||
const found = config.find({ Host: remoteIpAddress })
|
const found = config.find({ Host: remoteIpAddress })
|
||||||
if (!found) {
|
if (!found) {
|
||||||
config.append({
|
config.append({
|
||||||
Host: remoteIpAddress,
|
Host: remoteIpAddress,
|
||||||
Hostname: 'localhost',
|
Hostname: 'localhost',
|
||||||
Port: '11122',
|
Port: Number(localPort),
|
||||||
User: remoteUser,
|
User: remoteUser,
|
||||||
IdentityFile: sshKeyFile,
|
IdentityFile: sshKeyFile,
|
||||||
StrictHostKeyChecking: 'no'
|
StrictHostKeyChecking: 'no'
|
||||||
@ -516,11 +534,7 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
await fs.mkdir(`${homedir}/.ssh/`)
|
await fs.mkdir(`${homedir}/.ssh/`)
|
||||||
}
|
}
|
||||||
|
return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config))
|
||||||
await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config))
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export async function executeDockerCmd({ dockerId, command }: { dockerId: string, command: string }) {
|
export async function executeDockerCmd({ dockerId, command }: { dockerId: string, command: string }) {
|
||||||
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
||||||
|
@ -4,7 +4,7 @@ import sshConfig from 'ssh-config'
|
|||||||
import fs from 'fs/promises'
|
import fs from 'fs/promises'
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|
||||||
import { asyncExecShell, decrypt, errorHandler, executeDockerCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
|
import { asyncExecShell, createRemoteEngineConfiguration, decrypt, errorHandler, executeDockerCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
|
||||||
import { checkContainer } from '../../../../lib/docker';
|
import { checkContainer } from '../../../../lib/docker';
|
||||||
|
|
||||||
import type { OnlyId } from '../../../../types';
|
import type { OnlyId } from '../../../../types';
|
||||||
@ -30,7 +30,7 @@ export async function listDestinations(request: FastifyRequest<ListDestinations>
|
|||||||
destinations
|
destinations
|
||||||
}
|
}
|
||||||
} catch ({ status, message }) {
|
} catch ({ status, message }) {
|
||||||
console.log({status, message})
|
console.log({ status, message })
|
||||||
return errorHandler({ status, message })
|
return errorHandler({ status, message })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,32 +209,10 @@ export async function assignSSHKey(request: FastifyRequest) {
|
|||||||
export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: FastifyReply) {
|
export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: FastifyReply) {
|
||||||
try {
|
try {
|
||||||
const { id } = request.params;
|
const { id } = request.params;
|
||||||
const homedir = os.homedir();
|
await createRemoteEngineConfiguration(id);
|
||||||
|
|
||||||
const { sshKey: { privateKey }, remoteIpAddress, remotePort, remoteUser, network } = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } })
|
|
||||||
|
|
||||||
await fs.writeFile(`/tmp/id_rsa_verification_${id}`, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 })
|
|
||||||
|
|
||||||
|
const { remoteIpAddress, remoteUser, network } = await prisma.destinationDocker.findFirst({ where: { id } })
|
||||||
const host = `ssh://${remoteUser}@${remoteIpAddress}`
|
const host = `ssh://${remoteUser}@${remoteIpAddress}`
|
||||||
|
|
||||||
const config = sshConfig.parse('')
|
|
||||||
const found = config.find({ Host: remoteIpAddress })
|
|
||||||
if (!found) {
|
|
||||||
config.append({
|
|
||||||
Host: remoteIpAddress,
|
|
||||||
Port: remotePort.toString(),
|
|
||||||
User: remoteUser,
|
|
||||||
IdentityFile: `/tmp/id_rsa_verification_${id}`,
|
|
||||||
StrictHostKeyChecking: 'no'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await fs.stat(`${homedir}/.ssh/`)
|
|
||||||
} catch (error) {
|
|
||||||
await fs.mkdir(`${homedir}/.ssh/`)
|
|
||||||
}
|
|
||||||
await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config))
|
|
||||||
|
|
||||||
const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`);
|
const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`);
|
||||||
|
|
||||||
if (!stdout) {
|
if (!stdout) {
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
class="flex justify-center"
|
class="flex justify-center"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
type="button"
|
|
||||||
on:click
|
on:click
|
||||||
aria-pressed="false"
|
aria-pressed="false"
|
||||||
class="relative mx-20 inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out"
|
class="relative mx-20 inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user