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

Secure index with Access Key #365

Open
wants to merge 1 commit into
base: master
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
23 changes: 19 additions & 4 deletions webssh/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def get_pkey_obj(self):
class MixinHandler(object):

custom_headers = {
'Server': 'TornadoServer'
'You Should': 'Stay Out'
}

html = ('<html><head><title>{code} {reason}</title></head><body>{code} '
Expand Down Expand Up @@ -316,10 +316,11 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):

executor = ThreadPoolExecutor(max_workers=cpu_count()*5)

def initialize(self, loop, policy, host_keys_settings):
def initialize(self, loop, policy, host_keys_settings, access_key):
super(IndexHandler, self).initialize(loop)
self.policy = policy
self.host_keys_settings = host_keys_settings
self.access_key = access_key
self.ssh_client = self.get_ssh_client()
self.debug = self.settings.get('debug', False)
self.font = self.settings.get('font', '')
Expand Down Expand Up @@ -395,6 +396,10 @@ def get_args(self):
privatekey, filename = self.get_privatekey()
passphrase = self.get_argument('passphrase', u'')
totp = self.get_argument('totp', u'')
supplied_access_key = self.get_argument('access_key', u'')




if isinstance(self.policy, paramiko.RejectPolicy):
self.lookup_hostname(hostname, port)
Expand All @@ -405,7 +410,7 @@ def get_args(self):
pkey = None

self.ssh_client.totp = totp
args = (hostname, port, username, password, pkey)
args = (hostname, port, username, password, pkey, supplied_access_key)
logging.debug(args)

return args
Expand Down Expand Up @@ -488,7 +493,17 @@ def head(self):
pass

def get(self):
self.render('index.html', debug=self.debug, font=self.font)
# if path matches options.path
supplied_access_key = self.get_argument('accesskey', u'')

if self.debug:
logging.debug(f"Provided access key: {supplied_access_key}")
logging.debug(f"actual access key: {self.access_key}")

if supplied_access_key != self.access_key:
self.render('access_denied.html')
else:
self.render('index.html', debug=self.debug, font=self.font)

@tornado.gen.coroutine
def post(self):
Expand Down
8 changes: 6 additions & 2 deletions webssh/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@
from webssh.handler import IndexHandler, WsockHandler, NotFoundHandler
from webssh.settings import (
get_app_settings, get_host_keys_settings, get_policy_setting,
get_ssl_context, get_server_settings, check_encoding_setting
get_ssl_context, get_server_settings, check_encoding_setting,
get_access_key
)


def make_handlers(loop, options):
logging.info(options)
host_keys_settings = get_host_keys_settings(options)
policy = get_policy_setting(options, host_keys_settings)
access_key = get_access_key(options)

handlers = [
(r'/', IndexHandler, dict(loop=loop, policy=policy,
host_keys_settings=host_keys_settings)),
host_keys_settings=host_keys_settings,
access_key=access_key)),
(r'/ws', WsockHandler, dict(loop=loop))
]
return handlers
Expand Down
5 changes: 4 additions & 1 deletion webssh/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def print_version(flag):


define('address', default='', help='Listen address')
define('accesskey', default='', help='If provided, requests must have a matching url parameter')
define('port', type=int, default=8888, help='Listen port')
define('ssladdress', default='', help='SSL listen address')
define('sslport', type=int, default=4433, help='SSL listen port')
Expand Down Expand Up @@ -76,7 +77,7 @@ def get_url(self, filename, dirs):
def get_app_settings(options):
settings = dict(
template_path=os.path.join(base_dir, 'webssh', 'templates'),
static_path=os.path.join(base_dir, 'webssh', 'static'),
static_path=os.path.join(base_dir,'webssh', 'static'),
websocket_ping_interval=options.wpintvl,
debug=options.debug,
xsrf_cookies=options.xsrf,
Expand Down Expand Up @@ -126,6 +127,8 @@ def get_policy_setting(options, host_keys_settings):
check_policy_setting(policy_class, host_keys_settings)
return policy_class()

def get_access_key(options):
return options.accesskey

def get_ssl_context(options):
if not options.certfile and not options.keyfile:
Expand Down
8 changes: 8 additions & 0 deletions webssh/templates/access_denied.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<head> </head>
<body>
<h1>Access Denied</h1>
<p>Access key is not present or is invalid</p>

</body>
</html>