Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SSH certificate file in Node class #973

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ RUN python3 -m pip install --no-cache-dir /tmp/suzieq-$version-py3-none-any.whl
rm -rf /tmp/* /var/tmp/*

VOLUME [ "/home/$username/parquet" ]
ENV PATH=/root/.local/bin:$PATH:/root/.local/lib/python3.7/site-packages/suzieq/cli/:/root/.local/lib/python3.7/site-packages/suzieq/poller/:/root/.local/lib/python3.7/site-packages/suzieq/restServer

ENV PATH=/root/.local/bin:$PATH:/root/.local/lib/python3.9/site-packages/suzieq/cli/:/root/.local/lib/python3.9/site-packages/suzieq/poller/:/root/.local/lib/python3.9/site-packages/suzieq/restServer

ENV SQENV=docker

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile-sqbase
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8.14-slim-buster AS sqbase
FROM python:3.9.21-slim-bullseye AS sqbase

ENV PATH=/root/.local/bin:$PATH
ENV PYTHONPATH=/root/.local/lib
Expand Down
3 changes: 2 additions & 1 deletion build/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ python-dateutil==2.8.2 ; python_full_version > "3.8.1" and python_version < "3.1
python-dotenv==0.19.2 ; python_full_version > "3.8.1" and python_version < "3.10"
python-nubia==0.2b5 ; python_full_version > "3.8.1" and python_version < "3.10"
pytz==2023.3 ; python_full_version > "3.8.1" and python_version < "3.10"
pyvmomi==8.0.2.0.1 ; python_full_version > "3.8.1" and python_version < "3.10"
pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_full_version > "3.8.1" and python_version < "3.10"
pywinpty==2.0.11 ; python_full_version > "3.8.1" and python_version < "3.10" and os_name == "nt"
pyyaml==6.0 ; python_full_version > "3.8.1" and python_version < "3.10"
Expand Down Expand Up @@ -145,7 +146,7 @@ typing-extensions==4.7.1 ; python_full_version > "3.8.1" and python_version < "3
typing-inspect==0.9.0 ; python_full_version > "3.8.1" and python_version < "3.10"
tzlocal==2.1 ; python_full_version > "3.8.1" and python_version < "3.10"
urllib3==1.26.16 ; python_full_version > "3.8.1" and python_version < "3.10"
uvicorn==0.14.0 ; python_full_version > "3.8.1" and python_version < "3.10"
uvicorn==0.15.0 ; python_full_version > "3.8.1" and python_version < "3.10"
uvloop==0.17.0 ; python_full_version > "3.8.1" and python_version < "3.10"
validators==0.20.0 ; python_full_version > "3.8.1" and python_version < "3.10"
watchdog==3.0.0 ; python_full_version > "3.8.1" and python_version < "3.10" and platform_system != "Darwin"
Expand Down
12 changes: 6 additions & 6 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ faker = "~4.18"
netconan = "~0.11.2"
jsonpath-ng = "~1.6"
fastapi = "~0.95.2"
uvicorn = "^0.14.0"
uvicorn = "^0.15.0"
tabulate = "^0.8.7"
streamlit = "1.11.1"
graphviz = "^0.15"
Expand Down
53 changes: 27 additions & 26 deletions suzieq/poller/worker/nodes/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from urllib.parse import urlparse
import asyncio
from asyncio.subprocess import PIPE, DEVNULL
import os
# pylint: disable=redefined-builtin
from concurrent.futures._base import TimeoutError

Expand Down Expand Up @@ -141,27 +142,21 @@ async def initialize(self, **kwargs) -> TNode:
self.ssh_config_file = kwargs.get("ssh_config_file", None)
self.enable_password = kwargs.get('enable_password')

passphrase: str = kwargs.get("passphrase", None)
self.pvtkey_file = kwargs.get("ssh_keyfile", None)
self.jump_host_pvtkey_file = kwargs.get("jump_host_key_file", None)
self.passphrase: str = kwargs.get("passphrase", None)

jump_host = kwargs.get("jump_host", "")
if jump_host:
jump_result = urlparse(jump_host)
self.jump_user = jump_result.username or self.username
self.jump_host = jump_result.hostname
self.jump_host_key = None
if jump_result.port:
self.jump_port = jump_result.port
else:
self.jump_port = 22
pvtkey_file = kwargs.pop('jump_host_key_file')
if pvtkey_file:
self.jump_host_key = self._decrypt_pvtkey(pvtkey_file,
passphrase)
if not self.jump_host_key:
raise SqPollerConfError('Unable to read private key file'
f' at {pvtkey_file}')
else:
self.jump_host = None
self.jump_host_key = None

self.ignore_known_hosts = kwargs.get('ignore_known_hosts', False)
self.slow_host = kwargs.get('slow_host', False)
Expand All @@ -173,15 +168,6 @@ async def initialize(self, **kwargs) -> TNode:
# 4 is a number we picked to limit using up too many SSH sessions
# Many newer implementations allow upto 5 simultaneous SSH sessions
self.batch_size = 4
pvtkey_file = kwargs.get("ssh_keyfile", None)
if pvtkey_file:
self.pvtkey = self._decrypt_pvtkey(pvtkey_file, passphrase)
if not self.pvtkey:
self.logger.error("ERROR: Falling back to password for "
f"{self.address}:{self.port}")
self.pvtkey = None
else:
self.pvtkey = None

self._init_service_queue()

Expand Down Expand Up @@ -257,8 +243,8 @@ def _decrypt_pvtkey(self, pvtkey_file: str, passphrase: str) -> str:
passphrase)
except Exception as e: # pylint: disable=broad-except
self.logger.error(
f"ERROR: Unable to read private key file {pvtkey_file}"
f"for jump host due to {e}")
f"ERROR: Unable to read private key file {pvtkey_file} "
f"due to {e}")

return keydata

Expand Down Expand Up @@ -570,9 +556,10 @@ async def _init_jump_host_connection(
if self._tunnel:
return

if self.jump_host_key:
if self.jump_host_pvtkey_file:
jump_host_options = asyncssh.SSHClientConnectionOptions(
client_keys=self.jump_host_key,
client_keys=self.jump_host_pvtkey_file,
passphrase=self.passphrase,
connect_timeout=self.connect_timeout,
)

Expand Down Expand Up @@ -618,9 +605,7 @@ def _init_ssh_options(self) -> asyncssh.SSHClientConnectionOptions:
options = asyncssh.SSHClientConnectionOptions(
connect_timeout=self.connect_timeout,
username=self.username,
agent_identities=self.pvtkey if self.pvtkey else None,
client_keys=self.pvtkey if self.pvtkey else None,
password=self.password if not self.pvtkey else None,
password=self.password if not self.pvtkey_file else None,
kex_algs='+diffie-hellman-group1-sha1', # for older boxes
encryption_algs='+aes256-cbc', # for older boxes
)
Expand All @@ -635,6 +620,22 @@ def _init_ssh_options(self) -> asyncssh.SSHClientConnectionOptions:
config=[self.ssh_config_file],
)

if self.pvtkey_file:
# Giving just the filename let's asyncssh know to look for the
# corresponding cert file in the same directory.
# Ref: https://asyncssh.readthedocs.io/en/stable/api.html#specifying-private-keys
client_keys = self.pvtkey_file
options = asyncssh.SSHClientConnectionOptions(
options=options,
client_keys=client_keys,
)

if self.passphrase:
options = asyncssh.SSHClientConnectionOptions(
options=options,
passphrase=self.passphrase,
)

return options

async def _init_ssh(self, init_dev_data=True, use_lock=True) -> None:
Expand Down