Skip to content

Commit

Permalink
Commit liftoff#1: The Gate One beta is about to go public.
Browse files Browse the repository at this point in the history
  • Loading branch information
liftoff committed Oct 13, 2011
0 parents commit 04f2eab
Show file tree
Hide file tree
Showing 170 changed files with 35,150 additions and 0 deletions.
661 changes: 661 additions & 0 deletions AGPLv3.txt

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions LICENSE.txt
@@ -0,0 +1,18 @@
COPYRIGHT NOTICE
================
Gate One and all bundled original code...

Copyright 2011 Liftoff Software Corporation

Gate One is dual-licensed: AGPLv3 or Proprietary.

Unless you have been granted a license from Liftoff Software, Gate One and all
bundled software--except where noted--is licensed under the GNU Affero General
Public License version 3. A copy of the AGPLv3 license should have been
included with the Gate One software as AGPLv3.txt. If not, a copy may be
obtained by visiting:

http://www.gnu.org/licenses/agpl.html

If the terms of the AGPLv3 license do not suit your needs, a proprietary
license may be purchased from Liftoff Software: http://liftoffsoftware.com/
40 changes: 40 additions & 0 deletions README
@@ -0,0 +1,40 @@
Gate One is an HTML5 web-based terminal emulator and SSH client. Top features:

* No browser plugins required!
* Supports multiple simultaneous terminal sessions. As many as your
hardware can handle.
* Users can re-connect to their running terminals whenever they like from
anywhere.
* Can be embedded into other applications. Add a terminal--running whatever
application(s) you want--to your web app! Would be vastly superior to
say, a Java-based serial console applet (hint hint).
* Includes powerful plugin system that supports plugins written in Python,
JavaScript, and even CSS (yes, you can write a CSS-only plugin).
* The Gate One server can be stopped & started without users losing their
running terminal applications (even SSH sessions stay connected!). In
essence, worry-free upgrades!
* The SSH plugin allows users to duplicate sessions without having to
re-enter their username and password (it re-uses the existing SSH tunnel).
* Provides users with the ability to play back and save/share their terminal
sessions via a self-contained HTML playback file.
* Similarly, supports server-side logging, recording, and video-like
playback of user sessions. It can even log to syslog to support
whatever centralized logging system you want.
* Keberos-based Single Sign-on support is included. It even works with
Active Directory. Other authentication options are available as well.

All documentation is in the "gateone/docs" directory. The HTML documentation is
pre-built and ready-to-read.

IMPORTANT: Gate One is currently IN BETA. Some things may be incomplete or
buggy. Feel free to open new tickets in the issue tracker!

FYI: Gate One was developed entirely by one guy in his spare time over the
course of ~9 months. It turned out pretty good so he's looking to start a
business out of it. What better way to create jobs than to start by creating
one for yourself? All feedback, tips, and advice is appreciated:

daniel.mcdougall@liftoffsoftware.com

NOTE: http://liftoffsoftware.com/ hasn't been built yet so links pointing there
will be dead for a while.
216 changes: 216 additions & 0 deletions gateone/auth.py
@@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
#
# Copyright 2011 Liftoff Software Corporation
#

# Meta
__version__ = '0.9'
__license__ = "AGPLv3 or Proprietary (see LICENSE.txt)"
__version_info__ = (0, 9)
__author__ = 'Dan McDougall <daniel.mcdougall@liftoffsoftware.com>'

__doc__ = """\
Authentication
==============
This module contains Gate One's authentication classes. They map to Gate One's
--auth configuration option like so:
=============== ===================
--auth=none NullAuthHandler
--auth=kerberos KerberosAuthHandler
--auth=google GoogleAuthHandler
=============== ===================
None or Anonymous
-----------------
By default Gate One will not authenticate users. This means that user sessions
will be tied to their browser cookie and users will not be able to resume their
sessions from another computer/browser. Most useful for situations where
session persistence and logging aren't important.
*All* users will show up as %anonymous using this authentication type.
.. note:: The % is there to avoid name conflicts.
Kerberos
--------
Kerberos authentication utilizes GSSAPI for Single Sign-on (SSO) but will fall
back to HTTP Basic authentication if GSSAPI auth fails. This authentication
type can be integrated into any Kerberos infrastructure including Windows
Active Directory.
It is great for both transparent authentication and being able to tie sessions
and logs to specific users within your organization (compliance).
.. note:: The sso.py module itself has extensive documentation on this authentication type.
Google Authentication
---------------------
If you want persistent user sessions but don't care to run your own
authentication infrastructure this authentication type is for you. Assuming,
of course, that your Gate One server and clients will have access to the
Internet.
.. note:: This authentication type is perfect if you're using Chromebooks (Chrome OS devices).
Docstrings
==========
"""

# Import stdlib stuff
import os
import logging

# Import our own stuff
from utils import mkdir_p, generate_session_id

# 3rd party imports
import tornado.web
import tornado.auth
import tornado.escape

class BaseAuthHandler(tornado.web.RequestHandler):
"""The base class for all Gate One authentication handlers."""
def get_current_user(self):
"""Tornado standard method--implemented our way."""
user_json = self.get_secure_cookie("user")
if not user_json: return None
return tornado.escape.json_decode(user_json)

def user_login(self, user):
"""
Called immediately after a user authenticates successfully. Saves
session information in the user's directory. Expects *user* to be a
string containing the username or userPrincipalName. e.g. 'user@REALM'
or just 'someuser'.
"""
# Make a directory to store this user's settings/files/logs/etc
user_dir = self.settings['user_dir'] + "/" + user
logging.info("Creating user directory: %s" % user_dir)
mkdir_p(user_dir)
os.chmod(user_dir, 0700)
session_file = user_dir + '/session'
if os.path.exists(session_file):
session_data = open(session_file).read()
session_info = tornado.escape.json_decode(session_data)
else:
with open(session_file, 'w') as f:
# Save it so we can keep track across multiple clients
session_info = {
'go_upn': user, # FYI: UPN == userPrincipalName
'go_session': generate_session_id()
}
session_info_json = tornado.escape.json_encode(session_info)
f.write(session_info_json)
self.set_secure_cookie("user", tornado.escape.json_encode(session_info))

def user_logout(self, user):
"""
Called immediately after a user logs out. Doesn't actually do
anything. Just potential future use at this point.
"""
pass # Nothing here yet but someone might want to override it

class NullAuthHandler(BaseAuthHandler):
"""
A handler for when no authentication method is chosen (i.e. --auth=none).
"""
def get(self):
"""
Sets the 'user' cookie with a new random session ID (*go_session*) and
sets *go_upn* to '%anonymous'.
"""
# % is valid on the filesystem but invalid for an actual username.
# This ensures we won't have a conflict at some point with an actual
# user.
user = r'%anonymous'
self.user_login(user) # Takes care of the user's settings dir
user_cookie = {
'go_upn': user,
'go_session': generate_session_id()
}
self.set_secure_cookie("user", tornado.escape.json_encode(user_cookie))
next_url = self.get_argument("next", None)
if next_url:
self.redirect(next_url)
else:
self.redirect("/")

class GoogleAuthHandler(BaseAuthHandler, tornado.auth.GoogleMixin):
"""
Google authentication handler.
"""
@tornado.web.asynchronous
def get(self):
"""
Sets the 'user' cookie with an appropriate *go_upn* and *go_session*.
"""
if self.get_argument("openid.mode", None):
self.get_authenticated_user(self._on_auth)
return
self.authenticate_redirect(
ax_attrs=["name","email","language","username"])

def _on_auth(self, user):
"""
Just a continuation of the get() method (the final step where it
actually sets the cookie).
"""
if not user:
raise tornado.web.HTTPError(500, "Google auth failed")
print("GoogleAuthLoginHandler user: %s" % user)
# NOTE: Google auth 'user' will be a dict like so:
# user: {
# 'locale': u'en-us',
# 'first_name': u'Dan',
# 'last_name': u'McDougall',
# 'name': u'Dan McDougall',
# 'email': u'riskable@gmail.com'}
# Named these 'go_<whatever>' since that is less likely to conflict with
# anything in the future (should some auth mechanism start returning
# session IDs of some sort).
self.user_login(user) # This takes care of the user's settings dir
user_cookie = { # Don't need all that other stuff
'go_session': generate_session_id(),
'go_upn': user['email'] # Just an equivalent for standardization
}
self.set_secure_cookie("user", tornado.escape.json_encode(user_cookie))
next_url = self.get_argument("next", None)
if next_url:
self.redirect(next_url)
else:
self.redirect("/")

# Add our KerberosAuthHandler if sso is available
KerberosAuthHandler = None
try:
from sso import KerberosAuthMixin
class KerberosAuthHandler(BaseAuthHandler, KerberosAuthMixin):
"""
Handles authenticating users via Kerberos/GSSAPI/SSO.
"""
def get(self):
"""
Checks the user's request header for the proper Authorization data. If
it checks out the user will be logged in via _on_auth(). If not, the
browser will be redirected to login.
"""
auth_header = self.request.headers.get('Authorization')
if auth_header:
self.get_authenticated_user(self._on_auth)
return
self.authenticate_redirect()

def _on_auth(self, user):
if not user:
raise tornado.web.HTTPError(500, "Kerberos auth failed")
self.user_login(user) # This takes care of the user's settings dir
# TODO: Add some LDAP or local DB lookups here to add more detail to user objects
logging.debug("KerberosAuthHandler user: %s" % user)
next_url = self.get_argument("next", None)
if next_url:
self.redirect(next_url)
else:
self.redirect("/")
except ImportError:
pass # No SSO available.

0 comments on commit 04f2eab

Please sign in to comment.