-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathssh.py
More file actions
131 lines (109 loc) · 4.49 KB
/
ssh.py
File metadata and controls
131 lines (109 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import os
from fabric import task
from cloudy.sys.core import sys_reload_service, sys_restart_service
from cloudy.sys.etc import sys_etc_git_commit
from cloudy.util.context import Context
@task
@Context.wrap_context
def sys_ssh_set_port(c: Context, port: str = "22") -> None:
"""Set SSH port."""
sshd_config = "/etc/ssh/sshd_config"
c.sudo(f"sed -i 's/^#*Port .*/Port {port}/' {sshd_config}")
sys_etc_git_commit(c, f"Configured ssh (Port={port})")
# SSH port changes require restart, not just reload
sys_restart_service(c, "ssh")
# Give SSH a moment to fully restart
c.run("sleep 2")
@task
@Context.wrap_context
def sys_ssh_disable_root_login(c: Context) -> None:
"""Disable root login."""
sshd_config = "/etc/ssh/sshd_config"
c.sudo(f"sed -i 's/^#*PermitRootLogin .*/PermitRootLogin no/' {sshd_config}")
c.sudo("passwd -l root")
sys_etc_git_commit(c, "Disabled root login")
sys_reload_service(c, "ssh")
@task
@Context.wrap_context
def sys_ssh_disable_root_pass_login(c: Context) -> None:
"""Disable root password login but allow SSH key authentication."""
sshd_config = "/etc/ssh/sshd_config"
c.sudo(f"sed -i 's/^#*PermitRootLogin .*/PermitRootLogin prohibit-password/' {sshd_config}")
sys_etc_git_commit(c, "Disabled root password login (SSH keys still allowed)")
sys_reload_service(c, "ssh")
@task
@Context.wrap_context
def sys_ssh_enable_root_login(c: Context) -> None:
"""Enable root login."""
sshd_config = "/etc/ssh/sshd_config"
c.sudo(f"sed -i 's/^#*PermitRootLogin .*/PermitRootLogin yes/' {sshd_config}")
sys_etc_git_commit(c, "Enabled root login")
sys_reload_service(c, "ssh")
@task
@Context.wrap_context
def sys_ssh_enable_password_authentication(c: Context) -> None:
"""Enable password authentication."""
sshd_config = "/etc/ssh/sshd_config"
c.sudo(f"sed -i 's/^#*PasswordAuthentication .*/PasswordAuthentication yes/' {sshd_config}")
sys_etc_git_commit(c, "Enable password authentication")
sys_reload_service(c, "ssh")
@task
@Context.wrap_context
def sys_ssh_disable_password_authentication(c: Context) -> None:
"""Disable password authentication."""
sshd_config = "/etc/ssh/sshd_config"
c.sudo(f"sed -i 's/^#*PasswordAuthentication .*/PasswordAuthentication no/' {sshd_config}")
sys_etc_git_commit(c, "Disable password authentication")
sys_reload_service(c, "ssh")
@task
@Context.wrap_context
def sys_ssh_push_public_key(c: Context, user: str, pub_key: str = "~/.ssh/id_rsa.pub") -> None:
"""Install a public key on the remote server for a user."""
home_dir = "~" if user == "root" else f"/home/{user}"
ssh_dir = f"{home_dir}/.ssh"
auth_key = f"{ssh_dir}/authorized_keys"
pub_key = os.path.expanduser(pub_key)
if not os.path.exists(pub_key):
raise FileNotFoundError(f"Public key not found: {pub_key}")
c.sudo(f"mkdir -p {ssh_dir}")
c.put(pub_key, "/tmp/tmpkey")
c.sudo(f"sh -c 'cat /tmp/tmpkey >> {auth_key}'")
c.sudo("rm -f /tmp/tmpkey")
c.sudo(f"chown -R {user}:{user} {ssh_dir}")
c.sudo(f"chmod 700 {ssh_dir}")
c.sudo(f"chmod 600 {auth_key}")
@task
@Context.wrap_context
def sys_ssh_push_server_shared_keys(
c: Context, user: str, shared_dir: str = "~/.ssh/shared/ssh/"
) -> None:
"""Install shared SSH keys for a user (e.g., for GitHub access)."""
home_dir = "~" if user == "root" else f"/home/{user}"
key_dir = os.path.expanduser(shared_dir)
pri_key = os.path.join(key_dir, "id_rsa")
pub_key = os.path.join(key_dir, "id_rsa.pub")
for key in (pri_key, pub_key):
if not os.path.exists(key):
raise FileNotFoundError(f"Missing key file: {key}")
remote_ssh_dir = f"{home_dir}/.ssh"
c.sudo(f"mkdir -p {remote_ssh_dir}")
c.put(pri_key, f"{remote_ssh_dir}/id_rsa")
c.put(pub_key, f"{remote_ssh_dir}/id_rsa.pub")
c.sudo(f"chown -R {user}:{user} {remote_ssh_dir}")
c.sudo(f"chmod 700 {remote_ssh_dir}")
c.sudo(f"chmod 600 {remote_ssh_dir}/id_rsa")
c.sudo(f"chmod 644 {remote_ssh_dir}/id_rsa.pub")
def validate_ssh_config(ssh_port: str) -> None:
"""
Validate SSH configuration values.
Args:
ssh_port: SSH port to validate
Raises:
ValueError: If validation fails
"""
try:
port_num = int(ssh_port)
if not (1 <= port_num <= 65535):
raise ValueError(f"ssh-port must be between 1-65535, got: {ssh_port}")
except ValueError as exc:
raise ValueError(f"ssh-port must be a valid integer, got: {ssh_port}") from exc