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.
- hedockerssh-1.0.0/PKG-INFO +47 -0
- hedockerssh-1.0.0/README.md +30 -0
- hedockerssh-1.0.0/pyproject.toml +31 -0
- hedockerssh-1.0.0/pyproject.toml.orig +31 -0
- hedockerssh-1.0.0/src/hedockerssh/__init__.py +161 -0
- hedockerssh-1.0.0/src/hedockerssh/buildprofile/build.sh +60 -0
- hedockerssh-1.0.0/src/hedockerssh/buildprofile/docker/gnu +6 -0
- hedockerssh-1.0.0/src/hedockerssh/buildprofile/docker/musl +6 -0
- hedockerssh-1.0.0/src/hedockerssh/buildprofile/public/resetpasswd +10 -0
- hedockerssh-1.0.0/src/hedockerssh/buildprofile/public/run +10 -0
- hedockerssh-1.0.0/src/hedockerssh/buildprofile/scripts/build.sh +18 -0
- hedockerssh-1.0.0/src/hedockerssh/controller/container_manager.py +44 -0
- hedockerssh-1.0.0/src/hedockerssh/controller/env_manager.py +25 -0
- hedockerssh-1.0.0/src/hedockerssh/services/containermanager.py +149 -0
- hedockerssh-1.0.0/src/hedockerssh/services/core/env.py +3 -0
- hedockerssh-1.0.0/src/hedockerssh/services/core/tools/generatepasswd.py +15 -0
- hedockerssh-1.0.0/src/hedockerssh/services/core/tools/port_services.py +18 -0
- hedockerssh-1.0.0/src/hedockerssh/services/envmanager.py +65 -0
- hedockerssh-1.0.0/src/hedockerssh/services/newcontainer.py +69 -0
|
@@ -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,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,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}
|