hedockerssh 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: hedockerssh
3
+ Version: 1.0.0
4
+ Summary: Make your Docker container available as an SSH connection.
5
+ Author: undefined
6
+ Author-email: undefined <hestudio@hestudio.net>
7
+ License-Expression: MIT
8
+ Classifier: Operating System :: POSIX :: Linux
9
+ Classifier: Topic :: System :: Operating System Kernels :: Linux
10
+ Requires-Dist: passlib>=1.7.4
11
+ Requires-Dist: rich>=15.0.0
12
+ Requires-Python: >=3.14
13
+ Project-URL: Homepage, https://github.com/hestudio-community/dockerssh
14
+ Project-URL: Bug Tracker, https://github.com/hestudio-community/dockerssh/issues
15
+ Project-URL: Blog, https://www.hestudio.net/
16
+ Description-Content-Type: text/markdown
17
+
18
+ # DockerSSH
19
+
20
+ Make your Docker container available as an SSH connection.
21
+
22
+ ## Require
23
+
24
+ 1. Linux Only.
25
+ 2. bash.
26
+ 3. git.
27
+ 4. Latest docker.
28
+ 5. Root Permission.
29
+ 6. Latest Python LTS.
30
+ 7. uv
31
+
32
+ ## Install
33
+
34
+ 1. First install [uv](https://docs.astral.sh/uv).
35
+ 2. Run this command:
36
+
37
+ ```bash
38
+ uv tool install hedockerssh
39
+ ```
40
+
41
+ ### How to use?
42
+
43
+ You can view the manual using this command:
44
+
45
+ ```bash
46
+ dockerssh -h
47
+ ```
@@ -0,0 +1,30 @@
1
+ # DockerSSH
2
+
3
+ Make your Docker container available as an SSH connection.
4
+
5
+ ## Require
6
+
7
+ 1. Linux Only.
8
+ 2. bash.
9
+ 3. git.
10
+ 4. Latest docker.
11
+ 5. Root Permission.
12
+ 6. Latest Python LTS.
13
+ 7. uv
14
+
15
+ ## Install
16
+
17
+ 1. First install [uv](https://docs.astral.sh/uv).
18
+ 2. Run this command:
19
+
20
+ ```bash
21
+ uv tool install hedockerssh
22
+ ```
23
+
24
+ ### How to use?
25
+
26
+ You can view the manual using this command:
27
+
28
+ ```bash
29
+ dockerssh -h
30
+ ```
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "hedockerssh"
3
+ version = "1.0.0"
4
+ description = "Make your Docker container available as an SSH connection."
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ dependencies = [
8
+ "passlib>=1.7.4",
9
+ "rich>=15.0.0",
10
+ ]
11
+ classifiers = [
12
+ "Operating System :: POSIX :: Linux",
13
+ "Topic :: System :: Operating System Kernels :: Linux",
14
+ ]
15
+ license = "MIT"
16
+
17
+ [[project.authors]]
18
+ name = "undefined"
19
+ email = "hestudio@hestudio.net"
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/hestudio-community/dockerssh"
23
+ "Bug Tracker" = "https://github.com/hestudio-community/dockerssh/issues"
24
+ Blog = "https://www.hestudio.net/"
25
+
26
+ [project.scripts]
27
+ dockerssh = "hedockerssh:main"
28
+
29
+ [build-system]
30
+ requires = ["uv_build>=0.12.7,<0.13.0"]
31
+ build-backend = "uv_build"
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "hedockerssh"
3
+ version = "1.0.0"
4
+ description = "Make your Docker container available as an SSH connection."
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "undefined", email = "hestudio@hestudio.net" }
8
+ ]
9
+ requires-python = ">=3.14"
10
+ dependencies = [
11
+ "passlib>=1.7.4",
12
+ "rich>=15.0.0",
13
+ ]
14
+ classifiers = [
15
+ "Operating System :: POSIX :: Linux",
16
+ "Topic :: System :: Operating System Kernels :: Linux",
17
+ ]
18
+ license = "MIT"
19
+
20
+ [project.urls]
21
+ "Homepage" = "https://github.com/hestudio-community/dockerssh"
22
+ "Bug Tracker" = "https://github.com/hestudio-community/dockerssh/issues"
23
+ "Blog" = "https://www.hestudio.net/"
24
+
25
+
26
+ [project.scripts]
27
+ dockerssh = "hedockerssh:main"
28
+
29
+ [build-system]
30
+ requires = ["uv_build>=0.12.7,<0.13.0"]
31
+ build-backend = "uv_build"
@@ -0,0 +1,161 @@
1
+ import argparse
2
+ import platform
3
+ import sys
4
+
5
+ from hedockerssh.controller import container_manager
6
+ from hedockerssh.controller import env_manager
7
+
8
+
9
+ import shutil
10
+ import subprocess
11
+
12
+
13
+ def dockerchecker() -> bool:
14
+ dockercmd = shutil.which("docker")
15
+ if not dockercmd:
16
+ return False
17
+
18
+ r = subprocess.run(
19
+ [dockercmd, "info", "--format", "{{.ServerVersion}}"],
20
+ capture_output=True,
21
+ text=True,
22
+ timeout=30,
23
+ )
24
+ return r.returncode == 0
25
+
26
+
27
+ def main() -> None:
28
+ if not platform.system() == "Linux":
29
+ print("This program runs exclusively on Linux systems.")
30
+ sys.exit(1)
31
+ if not dockerchecker():
32
+ print("You do not have permission to use Docker.")
33
+ sys.exit(1)
34
+
35
+ # parser router
36
+ parser = argparse.ArgumentParser()
37
+
38
+ # /
39
+ parser_sub = parser.add_subparsers(dest="cmd", required=True, metavar="<command>")
40
+ container_parser = parser_sub.add_parser("container", help="Manager Container.")
41
+ env_parser = parser_sub.add_parser("env", help="Manager Environment.")
42
+
43
+ # /env
44
+ env_parser_sub = env_parser.add_subparsers(
45
+ dest="subcmd", required=True, metavar="<command>"
46
+ )
47
+ env_parser_sub.add_parser("list", help="List Installed Environment.")
48
+ install_env_parser = env_parser_sub.add_parser(
49
+ "install", help="Install Environment."
50
+ )
51
+ remove_env_parser = env_parser_sub.add_parser(
52
+ "remove", help="Remove Installed Environment."
53
+ )
54
+
55
+ # /env/install
56
+ install_env_parser.add_argument(
57
+ "-p", "--platform", required=True, type=str, help="e.g. linux/amd64"
58
+ )
59
+ install_env_parser.add_argument(
60
+ "-l", "--libc", required=True, type=str, help="e.g. gnu or musl"
61
+ )
62
+
63
+ # /env/remove
64
+ remove_env_parser.add_argument(
65
+ "-e",
66
+ "-env",
67
+ "--enviromnemt",
68
+ required=True,
69
+ type=str,
70
+ help="e.g. linux/amd64/gnu",
71
+ )
72
+
73
+ # /container
74
+ container_parser_sub = container_parser.add_subparsers(
75
+ dest="subcmd", required=True, metavar="<command>"
76
+ )
77
+ new_container_parser = container_parser_sub.add_parser("new", help="New Container.")
78
+ container_parser_sub.add_parser("list", help="List Container.")
79
+ resetpasswd_container_parser = container_parser_sub.add_parser(
80
+ "resetpasswd", help="Reset Container Password."
81
+ )
82
+ start_container_parser = container_parser_sub.add_parser(
83
+ "start", help="Start Container."
84
+ )
85
+ stop_container_parser = container_parser_sub.add_parser(
86
+ "stop", help="Stop Container."
87
+ )
88
+ restart_container_parser = container_parser_sub.add_parser(
89
+ "restart", help="Restart Container."
90
+ )
91
+ remove_container_parser = container_parser_sub.add_parser(
92
+ "remove", help="Remove Container."
93
+ )
94
+
95
+ # /container/new
96
+ new_container_parser.add_argument("-i", "--image", type=str, required=True)
97
+ new_container_parser.add_argument(
98
+ "-e",
99
+ "-env",
100
+ "--enviromnemt",
101
+ type=str,
102
+ required=True,
103
+ help="e.g. linux/amd64/gnu",
104
+ )
105
+ new_container_parser.add_argument("-p", "--port", type=int)
106
+ new_container_parser.add_argument("--passwd", type=str)
107
+
108
+ # /container/resetpasswd
109
+ resetpasswd_container_parser.add_argument(
110
+ "container", type=str, metavar="<container>"
111
+ )
112
+ resetpasswd_container_parser.add_argument("--passwd", type=str)
113
+
114
+ # /container/start
115
+ start_container_parser.add_argument("container", type=str, metavar="<container>")
116
+ # /container/stop
117
+ stop_container_parser.add_argument("container", type=str, metavar="<container>")
118
+ # /container/restart
119
+ restart_container_parser.add_argument("container", type=str, metavar="<container>")
120
+ # /container/remove
121
+ remove_container_parser.add_argument("container", type=str, metavar="<container>")
122
+
123
+ # args router
124
+ args = parser.parse_args()
125
+
126
+ match args.cmd:
127
+ case "container":
128
+ match args.subcmd:
129
+ case "new":
130
+ container_manager.new_container(
131
+ port=args.port,
132
+ image=args.image,
133
+ passwd=args.passwd,
134
+ env=args.enviromnemt,
135
+ )
136
+ case "list":
137
+ container_manager.list_container()
138
+ case "resetpasswd":
139
+ container_manager.resetpasswd_container(args.passwd, args.container)
140
+ case "start":
141
+ container_manager.start_container(args.container)
142
+ case "stop":
143
+ container_manager.stop_container(args.container)
144
+ case "restart":
145
+ container_manager.restart_container(args.container)
146
+ case "remove":
147
+ container_manager.remove_container(args.container)
148
+ case _:
149
+ container_parser.print_usage()
150
+ case "env":
151
+ match args.subcmd:
152
+ case "list":
153
+ env_manager.listinstalledenv()
154
+ case "install":
155
+ env_manager.installenv(platform=args.platform, libc=args.libc)
156
+ case "remove":
157
+ env_manager.removeinstalledenv(env=args.enviromnemt)
158
+ case _:
159
+ parser.print_usage()
160
+ case _:
161
+ parser.print_usage()
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+
3
+ export BASEPATH="/var/lib/dockerssh/server"
4
+ export SCRIPTPATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ export PLATFORM=$1
6
+ export LIBC=$2
7
+
8
+ echo "BASEPATH=$BASEPATH"
9
+ echo "SCRIPTPATH=$SCRIPTPATH"
10
+ echo "PLATFORM=$PLATFORM"
11
+ echo "LIBC=$LIBC"
12
+
13
+ if [[ ! -n $PLATFORM || ! -n $LIBC ]]; then
14
+ echo "require platform and libc."
15
+ exit
16
+ fi
17
+
18
+ mkdir -p $BASEPATH
19
+ cd $BASEPATH
20
+
21
+ if [[ $EUID -eq 0 ]]; then
22
+ echo "script run with root permission."
23
+ else
24
+ echo "script run without root permission."
25
+ exit
26
+ fi
27
+
28
+ if command -v docker &>/dev/null; then
29
+ echo "docker already install."
30
+ else
31
+ echo "docker not install."
32
+ exit
33
+ fi
34
+
35
+ if command -v git &>/dev/null; then
36
+ echo "git already install."
37
+ else
38
+ echo "git not install."
39
+ exit
40
+ fi
41
+
42
+ if [[ -f $SCRIPTPATH/docker/$LIBC ]]; then
43
+ export DROPBEAR_BUILDPATH="$BASEPATH/$PLATFORM/$LIBC"
44
+ echo "DROPBEAR_BUILDPATH=$BASEPATH/$PLATFORM/$LIBC"
45
+ if [ -e "$DROPBEAR_BUILDPATH" ]; then
46
+ rm -rf "$DROPBEAR_BUILDPATH"
47
+ echo remove "$DROPBEAR_BUILDPATH"
48
+ fi
49
+ mkdir -p $DROPBEAR_BUILDPATH
50
+ cd $DROPBEAR_BUILDPATH
51
+ cp $SCRIPTPATH/scripts/* $DROPBEAR_BUILDPATH
52
+ cp $SCRIPTPATH/docker/$LIBC $DROPBEAR_BUILDPATH/Dockerfile
53
+ git clone https://github.com/mkj/dropbear.git --depth 1
54
+ docker build --platform $PLATFORM -t dockerssh-build-$LIBC .
55
+ docker run --platform $PLATFORM -it --rm -v $DROPBEAR_BUILDPATH:/build dockerssh-build-$LIBC bash build.sh
56
+ cp $SCRIPTPATH/public/* $DROPBEAR_BUILDPATH/out
57
+ else
58
+ echo "dockerfile $LIBC not found."
59
+ exit
60
+ fi
@@ -0,0 +1,6 @@
1
+ FROM ubuntu:latest
2
+
3
+ WORKDIR /build
4
+ RUN apt update -y
5
+ RUN apt install bash -y
6
+ RUN apt install build-essential -y
@@ -0,0 +1,6 @@
1
+ FROM alpine:latest
2
+
3
+ WORKDIR /build
4
+ RUN apk update
5
+ RUN apk add --no-cache bash
6
+ RUN apk add --no-cache build-base
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+ if [ -n "$DOCKERSSH_PASSWD" ]; then
3
+ HASH=$(echo "$DOCKERSSH_PASSWD" | base64 -d)
4
+ if grep -q '^root:' /etc/shadow 2>/dev/null; then
5
+ sed -i "s|^root:.*|root:${HASH}:0:0:99999:7:::|" /etc/shadow
6
+ else
7
+ echo "root:${HASH}:0:0:99999:7:::" >> /etc/shadow
8
+ fi
9
+ unset DOCKERSSH_PASSWD
10
+ fi
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+ sh /var/lib/dockerssh/bin/resetpasswd $@
3
+ mkdir -p /var/lib/dockerssh/etc
4
+ /var/lib/dockerssh/bin/dropbearkey -t rsa -f /var/lib/dockerssh/etc/dropbear_rsa_host_key > /dev/null
5
+ /var/lib/dockerssh/bin/dropbearkey -t ecdsa -f /var/lib/dockerssh/etc/dropbear_ecdsa_host_key > /dev/null
6
+ /var/lib/dockerssh/bin/dropbearkey -t ed25519 -f /var/lib/dockerssh/etc/dropbear_ed25519_host_key > /dev/null
7
+ /var/lib/dockerssh/bin/dropbear -F -p 22 \
8
+ -r /var/lib/dockerssh/etc/dropbear_rsa_host_key \
9
+ -r /var/lib/dockerssh/etc/dropbear_ecdsa_host_key \
10
+ -r /var/lib/dockerssh/etc/dropbear_ed25519_host_key
@@ -0,0 +1,18 @@
1
+ #!/bin/bash
2
+
3
+ export DROPBEAR_BUILDPATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
+
5
+ cd $DROPBEAR_BUILDPATH
6
+ echo "DROPBEAR_BUILDPATH=$DROPBEAR_BUILDPATH"
7
+
8
+ cd $DROPBEAR_BUILDPATH/dropbear
9
+ ./configure --disable-zlib
10
+ make
11
+
12
+ cd $DROPBEAR_BUILDPATH
13
+ export DROPBEAR_OUT=$DROPBEAR_BUILDPATH/out
14
+ echo "DROPBEAR_OUT=$DROPBEAR_OUT"
15
+ mkdir -p $DROPBEAR_OUT
16
+ cp $DROPBEAR_BUILDPATH/dropbear/dropbear $DROPBEAR_OUT
17
+ cp $DROPBEAR_BUILDPATH/dropbear/dropbearconvert $DROPBEAR_OUT
18
+ cp $DROPBEAR_BUILDPATH/dropbear/dropbearkey $DROPBEAR_OUT
@@ -0,0 +1,44 @@
1
+ from hedockerssh.services import newcontainer
2
+ from hedockerssh.services import containermanager
3
+ from rich.table import Table
4
+ from rich.console import Console
5
+
6
+
7
+ def new_container(port: int | None, image: str, passwd: str | None, env: str):
8
+ newcontainer.single(port, image, passwd, env)
9
+
10
+
11
+ def list_container():
12
+ containerlist = containermanager.list_container()["containerlist"]
13
+ table = Table()
14
+ table.add_column("NAME")
15
+ table.add_column("PORT")
16
+ table.add_column("IMAGE")
17
+ table.add_column("LIBC")
18
+ table.add_column("PLATFORM")
19
+
20
+ for i in containerlist:
21
+ table.add_row(i["name"], str(i["port"]), i["image"], i["libc"], i["platform"])
22
+
23
+ console = Console()
24
+ console.print(table)
25
+
26
+
27
+ def resetpasswd_container(passwd: str | None, container: str):
28
+ containermanager.resetpasswd(passwd, container)
29
+
30
+
31
+ def start_container(container: str):
32
+ containermanager.start_container(container)
33
+
34
+
35
+ def stop_container(container: str):
36
+ containermanager.stop_container(container)
37
+
38
+
39
+ def restart_container(container: str):
40
+ containermanager.restart_container(container)
41
+
42
+
43
+ def remove_container(container: str):
44
+ containermanager.remove_container(container)
@@ -0,0 +1,25 @@
1
+ from rich.table import Table
2
+ from rich.console import Console
3
+
4
+ from hedockerssh.services import envmanager
5
+
6
+
7
+ def listinstalledenv():
8
+ envlist = envmanager.listinstalledenv()
9
+ table = Table()
10
+ table.add_column("PLATFORM")
11
+ table.add_column("LIBC")
12
+
13
+ for i in envlist:
14
+ base, libc = i.rsplit("/", 1)
15
+ table.add_row(base, libc)
16
+
17
+ console = Console()
18
+ console.print(table)
19
+
20
+
21
+ def installenv(platform: str, libc: str):
22
+ envmanager.installenv(platform, libc)
23
+
24
+ def removeinstalledenv(env: str):
25
+ envmanager.removeinstalledenv(env)
@@ -0,0 +1,149 @@
1
+ import subprocess
2
+ import json
3
+
4
+ from hedockerssh.services.core.tools import generatepasswd
5
+
6
+
7
+ def list_container():
8
+ try:
9
+ originoutput = subprocess.run(
10
+ [
11
+ "docker",
12
+ "ps",
13
+ "-a",
14
+ "--filter",
15
+ "label=dockerssh",
16
+ "--format",
17
+ '{"name":"{{.Names}}", "port":{{.Label "dockerssh"}}, "image":"{{.Image}}","libc":"{{.Label "dockerssh-libc"}}", "platform":"{{.Label "dockerssh-platform"}}"}',
18
+ ],
19
+ capture_output=True,
20
+ check=True,
21
+ )
22
+ except subprocess.CalledProcessError as e:
23
+ print(e.stderr.decode())
24
+ return {"code": "ERROR_PROCESS_ERROR"}
25
+
26
+ containerliststr = str(originoutput.stdout.decode("utf-8")).split("\n")[:-1]
27
+ containerlist = []
28
+ for i in containerliststr:
29
+ containerlist.append(json.loads(i))
30
+ return {"code": "SUCCESS", "containerlist": containerlist}
31
+
32
+
33
+ def resetpasswd(passwd: str | None, container: str):
34
+ if not container[0:10] == "dockerssh-":
35
+ print("This container is not a dockerssh container.")
36
+ return {"code": "ERROR_NO_DOCKERSSH_CONTAINER"}
37
+
38
+ if passwd == None:
39
+ passwd = generatepasswd.generatepasswd()
40
+ print(f"PASSWORD: {passwd}")
41
+ print("The password will only appear ONCE!!!")
42
+ passwd_base64 = generatepasswd.generatepasswdhash(passwd)
43
+
44
+ try:
45
+ subprocess.run(
46
+ [
47
+ "docker",
48
+ "exec",
49
+ "-e",
50
+ f"DOCKERSSH_PASSWD={passwd_base64}",
51
+ container,
52
+ "/var/lib/dockerssh/bin/resetpasswd",
53
+ ],
54
+ capture_output=True,
55
+ check=True,
56
+ )
57
+ except subprocess.CalledProcessError as e:
58
+ print(e.stderr.decode())
59
+ return {"code": "ERROR_PROCESS_ERROR"}
60
+ return {"code": "SUCCESS", "passwd": passwd}
61
+
62
+
63
+ def start_container(container: str):
64
+ if not container[0:10] == "dockerssh-":
65
+ print("This container is not a dockerssh container.")
66
+ return {"code": "ERROR_NO_DOCKERSSH_CONTAINER"}
67
+ try:
68
+ subprocess.run(
69
+ [
70
+ "docker",
71
+ "start",
72
+ container,
73
+ ],
74
+ capture_output=True,
75
+ check=True,
76
+ )
77
+ except subprocess.CalledProcessError as e:
78
+ print(e.stderr.decode())
79
+ return {"code": "ERROR_PROCESS_ERROR"}
80
+ return {"code": "SUCCESS"}
81
+
82
+
83
+ def stop_container(container: str):
84
+ if not container[0:10] == "dockerssh-":
85
+ print("This container is not a dockerssh container.")
86
+ return {"code": "ERROR_NO_DOCKERSSH_CONTAINER"}
87
+ try:
88
+ subprocess.run(
89
+ [
90
+ "docker",
91
+ "stop",
92
+ container,
93
+ ],
94
+ capture_output=True,
95
+ check=True,
96
+ )
97
+ except subprocess.CalledProcessError as e:
98
+ print(e.stderr.decode())
99
+ return {"code": "ERROR_PROCESS_ERROR"}
100
+ return {"code": "SUCCESS"}
101
+
102
+
103
+ def restart_container(container: str):
104
+ if not container[0:10] == "dockerssh-":
105
+ print("This container is not a dockerssh container.")
106
+ return {"code": "ERROR_NO_DOCKERSSH_CONTAINER"}
107
+ try:
108
+ subprocess.run(
109
+ [
110
+ "docker",
111
+ "restart",
112
+ container,
113
+ ],
114
+ capture_output=True,
115
+ check=True,
116
+ )
117
+ except subprocess.CalledProcessError as e:
118
+ print(e.stderr.decode())
119
+ return {"code": "ERROR_PROCESS_ERROR"}
120
+ return {"code": "SUCCESS"}
121
+
122
+
123
+ def remove_container(container: str):
124
+ if not container[0:10] == "dockerssh-":
125
+ print("This container is not a dockerssh container.")
126
+ return {"code": "ERROR_NO_DOCKERSSH_CONTAINER"}
127
+ try:
128
+ subprocess.run(
129
+ [
130
+ "docker",
131
+ "stop",
132
+ container,
133
+ ],
134
+ capture_output=True,
135
+ check=True,
136
+ )
137
+ subprocess.run(
138
+ [
139
+ "docker",
140
+ "rm",
141
+ container,
142
+ ],
143
+ capture_output=True,
144
+ check=True,
145
+ )
146
+ except subprocess.CalledProcessError as e:
147
+ print(e.stderr.decode())
148
+ return {"code": "ERROR_PROCESS_ERROR"}
149
+ return {"code": "SUCCESS"}
@@ -0,0 +1,3 @@
1
+ import pathlib
2
+
3
+ BASEPATH = pathlib.Path(__file__).resolve().parent.parent.parent
@@ -0,0 +1,15 @@
1
+ import base64
2
+ import secrets
3
+ import passlib.hash
4
+
5
+
6
+ def generatepasswdhash(passwd: str) -> str:
7
+ passwd_base64 = base64.b64encode(
8
+ str(passlib.hash.sha512_crypt.hash(passwd)).encode("utf-8")
9
+ )
10
+ return passwd_base64.decode("utf-8")
11
+
12
+
13
+ def generatepasswd() -> str:
14
+ passwd = secrets.token_hex(8)
15
+ return passwd
@@ -0,0 +1,18 @@
1
+ import random
2
+ import socket
3
+
4
+
5
+ def is_port_in_use(port: int, host: str = "0.0.0.0") -> bool:
6
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
7
+ try:
8
+ s.bind((host, port))
9
+ return False
10
+ except OSError:
11
+ return True
12
+
13
+
14
+ def generate_port():
15
+ while True:
16
+ port = random.randint(49152, 65535)
17
+ if not is_port_in_use(port):
18
+ return port
@@ -0,0 +1,65 @@
1
+ import subprocess
2
+ import pathlib
3
+ import shutil
4
+
5
+ from hedockerssh.services.core.env import BASEPATH
6
+
7
+
8
+ def listplatformsupport() -> dict:
9
+ try:
10
+ origin = subprocess.run(
11
+ ["docker", "buildx", "ls", "--format", "{{.Platforms}}"],
12
+ capture_output=True,
13
+ check=True,
14
+ )
15
+ except subprocess.CalledProcessError as e:
16
+ print(e.stderr.decode())
17
+ return {"code": "ERROR_PROCESS_ERROR"}
18
+ return {
19
+ "code": "SUCCESS",
20
+ "platformsupport": origin.stdout.decode("utf-8")
21
+ .replace("\n", "")
22
+ .replace(" ", "")
23
+ .split(","),
24
+ }
25
+
26
+
27
+ def checkplatformsupport(platform: str) -> bool:
28
+ if platform in listplatformsupport()["platformsupport"]:
29
+ return True
30
+ else:
31
+ return False
32
+
33
+
34
+ def listinstalledenv() -> list:
35
+ base = pathlib.Path("/var/lib/dockerssh/server")
36
+ return sorted("/".join(p.parts[-3:]) for p in base.glob("*/*/*"))
37
+
38
+
39
+ def checkinstalledenv(env: str) -> bool:
40
+ if env in listinstalledenv():
41
+ return True
42
+ else:
43
+ return False
44
+
45
+
46
+ def installenv(platform: str, libc: str):
47
+ if not checkplatformsupport(platform):
48
+ print("Your Docker doesn't support this platform.")
49
+ return {"code": "ERROR_PLATFORM_NOT_SUPPORT"}
50
+ subprocess.run(["bash", f"{BASEPATH}/buildprofile/build.sh", platform, libc])
51
+ return {"code": "SUCCESS"}
52
+
53
+
54
+ def removeinstalledenv(env: str):
55
+ if not checkinstalledenv(env):
56
+ print("The platform is not installed.")
57
+ return {"code": "ERROR_NOT_INSTALLED"}
58
+
59
+ try:
60
+ shutil.rmtree(f"/var/lib/dockerssh/server/{env}")
61
+ except PermissionError:
62
+ print("Permission denied.")
63
+ return {"code": "ERROR_NO_PERMISSION"}
64
+
65
+ return {"code": "SUCCESS"}
@@ -0,0 +1,69 @@
1
+ import secrets
2
+ import subprocess
3
+
4
+
5
+ from hedockerssh.services.core.env import BASEPATH
6
+ from hedockerssh.services.core.tools import port_services
7
+ from hedockerssh.services.core.tools import generatepasswd
8
+ from hedockerssh.services.envmanager import checkinstalledenv
9
+
10
+
11
+ def single(port: int | None, image: str, passwd: str | None, env: str) -> dict:
12
+ if not checkinstalledenv(env):
13
+ print("The platform is not installed.")
14
+ return {"code": "ERROR_NOT_INSTALLED"}
15
+
16
+ base, libc = env.rsplit("/", 1)
17
+
18
+ if port == None:
19
+ port = port_services.generate_port()
20
+ print(f"PORT: {port}")
21
+ else:
22
+ if not (1 <= port <= 65535):
23
+ print("the port must be between 1 and 65535. exiting...")
24
+ return {"code": "ERROR_PORT_SCOPE"}
25
+ elif port_services.is_port_in_use(port):
26
+ print("this port is already in use. exiting...")
27
+ return {"code": "ERROR_PORT_USED"}
28
+
29
+ if passwd == None:
30
+ passwd = generatepasswd.generatepasswd()
31
+ print(f"PASSWORD: {passwd}")
32
+ print("The password will only appear ONCE!!!")
33
+ passwd_base64 = generatepasswd.generatepasswdhash(passwd)
34
+
35
+ try:
36
+ subprocess.run(
37
+ [
38
+ "docker",
39
+ "run",
40
+ "--name",
41
+ f"dockerssh-{secrets.token_hex(4)}",
42
+ "--platform",
43
+ base,
44
+ "-d",
45
+ "-it",
46
+ "-l",
47
+ f"dockerssh={port}",
48
+ "-l",
49
+ f"dockerssh-libc={libc}",
50
+ "-l",
51
+ f"dockerssh-platform={base}",
52
+ "-v",
53
+ f"/var/lib/dockerssh/server/{env}/out:/var/lib/dockerssh/bin:ro",
54
+ "-p",
55
+ f"{str(port)}:22",
56
+ "-e",
57
+ f"DOCKERSSH_PASSWD={passwd_base64}",
58
+ image,
59
+ "sh"
60
+ "/var/lib/dockerssh/bin/run",
61
+ ],
62
+ capture_output=True,
63
+ check=True,
64
+ )
65
+ except subprocess.CalledProcessError as e:
66
+ print(e.stderr.decode())
67
+ return {"code": "ERROR_PROCESS_ERROR"}
68
+
69
+ return {"code": "SUCCESS", "port": port, "passwd": passwd, "image": image}