Skip to content

Commit

Permalink
Added option for ssh_port
Browse files Browse the repository at this point in the history
This option will set the ssh port for VMs using a Public IP and set
the necessary NSG rule to allow access.
  • Loading branch information
edwardsp committed Mar 1, 2022
1 parent 6b83180 commit 3f1460d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 12 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,12 @@ The following properties are global :
| **location** | The region where the resources are created | yes | |
| **resource_group** | The resource group to put the resources | yes | |
| **install_from** | The resource where the install script will be run | no | |
| **ssh_port** | The port to use for SSH | no | 22 |
| **admin_user** | The admin user for all resources | yes | |
| **proximity_placement_group_name** | The proximity group name to create | no | |
| **global_tags** | Global tags to apply to all ARM resources | no | |

The `azhpc-build` command will generate an install script from the configuration file. This will be run from the `install_from` VM. The `install_from` VM must either have a public IP address or be accessible by hostname from where `azhpc-build` is run (i.e. run `azhpc-build` from a VM on the same vnet).
The `azhpc-build` command will generate an install script from the configuration file. This will be run from the `install_from` VM. The `install_from` VM must either have a public IP address or be accessible by hostname from where `azhpc-build` is run (i.e. run `azhpc-build` from a VM on the same vnet). The `ssh_port` refers to an _additional_ port number where the ssh daemon will listen on VMs with a public IP address. The NSG rules will only be applied to the `ssh_port` number although port 22 will be accessible from within the vnet.

### Network dictionary

Expand Down
8 changes: 7 additions & 1 deletion pyazhpc/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ def __helper_arm_add_zones(self, res, zones):

def _add_vm(self, cfg, r, vnet_in_deployment):
res = cfg["resources"][r]
rsshport = cfg.get("ssh_port", 22)
rtype = res["type"]
rsize = res["vm_type"]
rimage = res["image"]
Expand Down Expand Up @@ -504,6 +505,11 @@ def _add_vm(self, cfg, r, vnet_in_deployment):
with open(adminuser+"_id_rsa.pub") as f:
sshkey = f.read().strip()

if rsshport != 22:
if customdata:
log.error("Cannot specify custom data with a non-standard SSH port for VMs with a public IP.")
customdata = f"#!/bin/bash\nsed -i \"s/^#Port 22/Port 22\\nPort {rsshport}/\" /etc/ssh/sshd_config\nsemanage port -a -t ssh_port_t -p tcp {rsshport}\nsystemctl restart sshd\n"

if ravset and ravset not in self.avsets:
arm_avset = {
"name": ravset,
Expand Down Expand Up @@ -590,7 +596,7 @@ def _add_vm(self, cfg, r, vnet_in_deployment):
"properties": {
"protocol": "Tcp",
"sourcePortRange": "*",
"destinationPortRange": "22",
"destinationPortRange": str(rsshport),
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
Expand Down
19 changes: 14 additions & 5 deletions pyazhpc/azhpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ def do_scp(args):
sshkey="{}_id_rsa".format(adminuser)
# TODO: check ssh key exists

sshport = c.read_value("ssh_port", 22)

fqdn = c.get_install_from_destination()
if not fqdn:
log.error(f"Missing 'install_from' property")
Expand All @@ -183,7 +185,7 @@ def do_scp(args):
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-i", sshkey,
"-o", f"ProxyCommand=ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {sshkey} -W %h:%p {adminuser}@{fqdn}"
"-o", f"ProxyCommand=ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p {sshport} -i {sshkey} -W %h:%p {adminuser}@{fqdn}"
] + scp_args
log.debug(" ".join([ f"'{a}'" for a in scp_cmd ]))
os.execvp(scp_exe, scp_cmd)
Expand All @@ -201,6 +203,8 @@ def do_connect(args):
sshuser = adminuser
else:
sshuser = args.user

sshport = c.read_value("ssh_port", 22)

jumpbox = c.read_value("install_from")
if not jumpbox:
Expand Down Expand Up @@ -277,6 +281,7 @@ def do_connect(args):
"ssh", "-t", "-q",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-p", str(sshport),
"-i", ssh_private_key,
f"{sshuser}@{fqdn}"
]
Expand All @@ -289,18 +294,19 @@ def do_connect(args):
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-i", ssh_private_key,
"-o", f"ProxyCommand=ssh -i {ssh_private_key} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -W %h:%p {sshuser}@{fqdn}",
"-o", f"ProxyCommand=ssh -p {sshport} -i {ssh_private_key} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -W %h:%p {sshuser}@{fqdn}",
f"{sshuser}@{target}"
]
log.debug(" ".join(ssh_args + cmdline))
os.execvp(ssh_exe, ssh_args + cmdline)

def _exec_command(fqdn, sshuser, sshkey, cmdline):
def _exec_command(fqdn, sshuser, sshport, sshkey, cmdline):
ssh_exe = "ssh"
ssh_args = [
ssh_exe, "-q",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-p", str(sshport),
"-i", sshkey,
f"{sshuser}@{fqdn}"
]
Expand All @@ -314,14 +320,15 @@ def do_status(args):

adminuser = c.read_value("admin_user")
ssh_private_key="{}_id_rsa".format(adminuser)
sshport = c.read_value("ssh_port", 22)

fqdn = c.get_install_from_destination()
if not fqdn:
log.error(f"Missing 'install_from' property")
sys.exit(1)

tmpdir = "azhpc_install_" + os.path.basename(args.config_file).strip(".json")
_exec_command(fqdn, adminuser, ssh_private_key, f"pssh -h {tmpdir}/hostlists/linux -i -t 0 'printf \"%-20s%s\n\" \"$(hostname)\" \"$(uptime)\"' | grep -v SUCCESS")
_exec_command(fqdn, adminuser, sshport, ssh_private_key, f"pssh -h {tmpdir}/hostlists/linux -i -t 0 'printf \"%-20s%s\n\" \"$(hostname)\" \"$(uptime)\"' | grep -v SUCCESS")


def do_run(args):
Expand All @@ -338,6 +345,8 @@ def do_run(args):
else:
sshuser = args.user

sshport = c.read_value("ssh_port", 22)

jumpbox = c.read_value("install_from")
if not jumpbox:
log.error(f"Missing 'install_from' property")
Expand Down Expand Up @@ -368,7 +377,7 @@ def do_run(args):

hostlist = " ".join(hosts)
cmd = " ".join(args.args)
_exec_command(fqdn, sshuser, ssh_private_key, f"pssh -H '{hostlist}' -i -t 0 '{cmd}'")
_exec_command(fqdn, sshuser, sshport, ssh_private_key, f"pssh -H '{hostlist}' -i -t 0 '{cmd}'")

def _create_private_key(private_key_file, public_key_file):
if not (os.path.exists(private_key_file) and os.path.exists(public_key_file)):
Expand Down
13 changes: 8 additions & 5 deletions pyazhpc/azinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,10 @@ def generate_cc_clusters(config, tmpdir):
f.write(json.dumps(cluster_params, indent=4))
__cyclecloud_create_cluster(cluster_template, cluster_name, cluster_json)

def __rsync(sshkey, src, dst):
def __rsync(sshkey, sshport, src, dst):
cmd = [
"rsync", "-a", "--timeout=60", "-e",
f"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {sshkey}",
f"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p {sshport} -i {sshkey}",
src, dst
]
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Expand All @@ -426,6 +426,7 @@ def __rsync(sshkey, src, dst):

def run(cfg, tmpdir, adminuser, sshprivkey, sshpubkey, fqdn, startstep=0):
jb = cfg.get("install_from")
sshport = cfg.get("ssh_port")
install_steps = [{ "script": "install_node_setup.sh" }] + cfg.get("install", [])
if jb:
log.debug("wait for ssh on jumpbox")
Expand All @@ -435,6 +436,7 @@ def run(cfg, tmpdir, adminuser, sshprivkey, sshpubkey, fqdn, startstep=0):
"ssh",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-p", str(sshport),
"-i", sshprivkey,
f"{adminuser}@{fqdn}",
"hostname"
Expand All @@ -451,7 +453,7 @@ def run(cfg, tmpdir, adminuser, sshprivkey, sshpubkey, fqdn, startstep=0):
time.sleep(10)

log.debug("rsyncing install files")
__rsync(sshprivkey, tmpdir, f"{adminuser}@{fqdn}:.")
__rsync(sshprivkey, sshport, tmpdir, f"{adminuser}@{fqdn}:.")

for idx, step in enumerate(install_steps):
if idx == 0 and not jb:
Expand All @@ -477,13 +479,14 @@ def run(cfg, tmpdir, adminuser, sshprivkey, sshpubkey, fqdn, startstep=0):
"ssh",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-p", str(sshport),
"-i", sshprivkey,
f"{adminuser}@{fqdn}"
] + instcmd
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if res.returncode != 0:
log.error("invalid returncode"+_make_subprocess_error_string(res))
__rsync(sshprivkey, f"{adminuser}@{fqdn}:{tmpdir}/install/*.log", f"{tmpdir}/install/.")
__rsync(sshprivkey, sshport, f"{adminuser}@{fqdn}:{tmpdir}/install/*.log", f"{tmpdir}/install/.")
sys.exit(1)
else:
log.warning("skipping step as no jumpbox (install_from) is set")
Expand All @@ -502,5 +505,5 @@ def run(cfg, tmpdir, adminuser, sshprivkey, sshpubkey, fqdn, startstep=0):

if jb:
log.debug("rsyncing log files back")
__rsync(sshprivkey, f"{adminuser}@{fqdn}:{tmpdir}/install/*.log", f"{tmpdir}/install/.")
__rsync(sshprivkey, sshport, f"{adminuser}@{fqdn}:{tmpdir}/install/*.log", f"{tmpdir}/install/.")

0 comments on commit 3f1460d

Please sign in to comment.