Ejemplo n.º 1
0
def test_notebook(admin_passwd,
                  secure=False,
                  directory=None,
                  port=8050,
                  interface='localhost',
                  verbose=False):
    """
    This function is used to test notebook server functions.

    EXAMPLES::

        sage: from sagenb.notebook.notebook_object import test_notebook
        sage: passwd = str(randint(1,1<<128))
        sage: nb = test_notebook(passwd, interface='localhost', port=8060)
        sage: import urllib
        sage: h = urllib.urlopen('http://localhost:8060')
        sage: homepage = h.read()
        sage: h.close()
        sage: 'html' in homepage
        True
        sage: nb.dispose()
    """
    import socket, pexpect

    if directory is None:
        directory = tmp_dir = tempfile.mkdtemp()
    else:
        tmp_dir = None

    if not os.path.exists(directory):
        os.makedirs(directory)

    nb = _notebook.load_notebook(directory)
    nb.set_accounts(True)
    nb.add_user('admin', admin_passwd, '')
    nb.set_accounts(False)
    nb.save()

    p = notebook(directory=directory,
                 accounts=True,
                 secure=secure,
                 port=port,
                 interface=interface,
                 automatic_login=False,
                 fork=True,
                 quiet=True)
    p.expect("Starting factory")

    def dispose():
        try:
            p.send('\x03')  # control-C
        except pexpect.EOF:
            pass
        p.close(force=True)
        shutil.rmtree(nb._dir)

    p.dispose = dispose
    if verbose:
        print "Notebook started."
    return p
Ejemplo n.º 2
0
def test_notebook(admin_passwd, secure=False, directory=None, port=8050, interface="localhost", verbose=False):
    """
    This function is used to test notebook server functions.
    
    EXAMPLES::
    
        sage: from sagenb.notebook.notebook_object import test_notebook
        sage: passwd = str(randint(1,1<<128))
        sage: nb = test_notebook(passwd, interface='localhost', port=8060)
        sage: import urllib
        sage: h = urllib.urlopen('http://localhost:8060')
        sage: homepage = h.read()
        sage: h.close()
        sage: 'html' in homepage
        True
        sage: nb.dispose()
    """
    import socket, pexpect

    if directory is None:
        directory = tmp_dir = tempfile.mkdtemp()
    else:
        tmp_dir = None

    if not os.path.exists(directory):
        os.makedirs(directory)

    nb = _notebook.load_notebook(directory)
    nb.set_accounts(True)
    nb.add_user("admin", admin_passwd, "")
    nb.set_accounts(False)
    nb.save()

    p = notebook(
        directory=directory,
        accounts=True,
        secure=secure,
        port=port,
        interface=interface,
        automatic_login=False,
        fork=True,
        quiet=True,
    )
    p.expect("Starting factory")

    def dispose():
        try:
            p.send("\x03")  # control-C
        except pexpect.EOF:
            pass
        p.close(force=True)
        shutil.rmtree(nb._dir)

    p.dispose = dispose
    if verbose:
        print "Notebook started."
    return p
Ejemplo n.º 3
0
def notebook_twisted(self,
             directory     = None,
             port          = 8000,
             interface     = 'localhost',
             address       = None,
             port_tries    = 50,
             secure        = False,
             reset         = False,
             accounts      = False,
             require_login = True,

             server_pool   = None,
             ulimit        = '',

             timeout       = 0,

             open_viewer   = True,

             sagetex_path  = "",
             start_path    = "",
             fork          = False,
             quiet         = False,

             subnets       = None):
    cwd = os.getcwd()
    # For backwards compatible, we still allow the address to be set
    # instead of the interface argument
    if address is not None:
        from warnings import warn
        message = "Use 'interface' instead of 'address' when calling notebook(...)."
        warn(message, DeprecationWarning, stacklevel=3)
        interface = address

    if directory is None:
        directory = '%s/sage_notebook' % DOT_SAGENB
    else:
        if (isinstance(directory, basestring) and len(directory) > 0 and
            directory[-1] == "/"):
            directory = directory[:-1]

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    nb = notebook.load_notebook(directory)

    directory = nb._dir
    conf = os.path.join(directory, 'twistedconf.tac')

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)

    if nb.user_exists('root') and not nb.user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if reset:
            nb.user('admin').set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)
    nb.set_accounts(accounts)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."

    nb.save()
    del nb

    def run(port, subnets):
        # Is a server already running? Check if a Twistd PID exists in
        # the given directory.
        pidfile = os.path.join(directory, 'twistd.pid')
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())

                if str(e).startswith('Another twistd server is running,'):
                    print 'Another Sage Notebook server is running, PID %d.' % pid
                    old_interface, old_port, old_secure = get_old_settings(conf)
                    if open_viewer and old_port:
                        old_interface = old_interface or 'localhost'

                        print 'Opening web browser at http%s://%s:%s/ ...' % (
                            's' if old_secure else '', old_interface, old_port)

                        from sagenb.misc.misc import open_page as browse_to
                        browse_to(old_interface, old_port, old_secure, '/')
                        return
                    print '\nPlease either stop the old server or run the new server in a different directory.'
                    return

        ## Create the config file
        if secure:
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s' % (
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            if require_login:
                start_path = "'/?startup_token=%s' % startup_token"
            else:
                start_path = "'/'"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        if subnets is None:
            factory = "factory = channel.HTTPFactory(site)"
        else:
            if not isinstance(subnets, (list, tuple)):
                subnets = [subnets]
            factory = """
# See http://stackoverflow.com/questions/1273297/python-twisted-restricting-access-by-ip-address
from sagenb.misc.ipaddr import IPNetwork
subnets = eval(r"%s")
if not any(s.startswith('127') for s in subnets):
    subnets.insert(0, '127.0.0.0/8')
subnets = [IPNetwork(x) for x in subnets]
class RestrictedIPFactory(channel.HTTPFactory):
    def buildProtocol(self, addr):
        a = str(addr.host)
        for X in subnets:
            if a in X:
                return channel.HTTPFactory.buildProtocol(self, addr)
        print 'Ignoring all requests from IP address '+str(addr.host)

factory = RestrictedIPFactory(site)
""" % tuple([subnets])

        config.write("""
####################################################################
# WARNING -- Do not edit this file!   It is autogenerated each time
# the notebook(...) command is executed.
####################################################################
from twisted.internet import reactor

# Now set things up and start the notebook
import sagenb.notebook.notebook
sagenb.notebook.notebook.JSMATH=True
import sagenb.notebook.notebook as notebook
import sagenb.notebook.twist as twist
twist.notebook = notebook.load_notebook(%s)
twist.SAGETEX_PATH = %r
twist.OPEN_MODE = %s
twist.SID_COOKIE = str(hash(%r))
twist.DIR = %r
twist.reactor = reactor
twist.init_updates()
import sagenb.notebook.worksheet as worksheet

import signal, sys, random
def save_notebook():
    from twisted.internet.error import ReactorNotRunning
    print "Quitting all running worksheets..."
    twist.notebook.quit()
    print "Saving notebook..."
    twist.notebook.save()
    print "Notebook cleanly saved."

def my_sigint(x, n):
    try:
        reactor.stop()
    except ReactorNotRunning:
        pass
    signal.signal(signal.SIGINT, signal.SIG_DFL)


signal.signal(signal.SIGINT, my_sigint)

## Disable client-side certificate request for gnutls
try:
    import gnutls.connection
    gnutls.connection.CERT_REQUEST = 0
except (OSError, ImportError):
    print "Note: GNUTLS not available."


## Authentication framework (ported from Knooboo)
from twisted.web2 import log, server, channel
from twisted.cred import portal, checkers, credentials
import sagenb.notebook.guard as guard
import sagenb.notebook.avatars as avatars

from twisted.cred import portal

realm = avatars.LoginSystem()
p = portal.Portal(realm)
startup_token = '%%x' %% random.randint(0, 2**128)
startup_checker = avatars.OneTimeTokenChecker()
startup_checker.token = startup_token
p.registerChecker(startup_checker)
password_checker = avatars.PasswordChecker()
p.registerChecker(password_checker)
p.registerChecker(checkers.AllowAnonymousAccess())
rsrc = guard.MySessionWrapper(p)
log.DefaultCommonAccessLoggingObserver().start()
site = server.Site(rsrc)
%s
from twisted.web2 import channel
from twisted.application import service, strports
application = service.Application("SAGE Notebook")
s = strports.service(%r, factory)
%s
s.setServiceParent(application)

reactor.addSystemEventTrigger('before', 'shutdown', save_notebook)

""" % (notebook_opts, sagetex_path, not require_login,
       os.path.abspath(directory), cwd, factory,
       strport, open_page))

        config.close()

        ## Start up twisted
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, conf)
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
                           port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
        # end of inner function run

    if interface != 'localhost' and not secure:
            print "*" * 70
            print "WARNING: Insecure notebook server listening on external interface."
            print "Unless you are running this via ssh port forwarding, you are"
            print "**crazy**!  You should run the notebook with the option secure=True."
            print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port, subnets)
Ejemplo n.º 4
0
def notebook_run(self,
             directory     = None,
             port          = 8080,
             interface     = 'localhost',
             port_tries    = 50,
             secure        = False,
             reset         = False,
             accounts      = None,
             openid        = None,

             server_pool   = None,
             ulimit        = '',

             timeout       = 0,

             upload        = None,
             automatic_login = True,

             start_path    = "",
             fork          = False,
             quiet         = False,

             server = "twistd",
             profile = False,

             subnets = None,
             require_login = None,
             open_viewer = None,
             address = None,
             ):

    # Check whether pyOpenSSL is installed or not (see Sage trac #13385)
    if secure:
        try:
            import OpenSSL
        except ImportError:
            raise RuntimeError("HTTPS cannot be used without pyOpenSSL"
                    " installed. See the Sage README for more information.")

    # Turn it into a full path for later conversion to a file URL
    if upload:
        upload_abs = os.path.abspath(upload)
        if os.path.exists(upload_abs):
            upload = upload_abs
        else:
            # They might have expected ~ to be expanded to their user directory
            upload = os.path.expanduser(upload)
            if not os.path.exists(upload):
                raise ValueError("Unable to find the file %s to upload" % upload)


    if subnets is not None:
        raise ValueError("""The subnets parameter is no longer supported. Please use a firewall to block subnets, or even better, volunteer to write the code to implement subnets again.""")
    if require_login is not None or open_viewer is not None:
        raise ValueError("The require_login and open_viewer parameters are no longer supported.  "
                         "Please use automatic_login=True to automatically log in as admin, "
                         "or use automatic_login=False to not automatically log in.")
    if address is not None:
        raise ValueError("Use 'interface' instead of 'address' when calling notebook(...).")

    cwd = os.getcwd()

    if directory is None:
        directory = '%s/sage_notebook.sagenb' % DOT_SAGENB
    else:
        directory = directory.rstrip('/')
        if not directory.endswith('.sagenb'):
            directory += '.sagenb'

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]
    pidfile = os.path.join(directory, 'sagenb.pid')

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    # first use provided values, if none, use loaded values,
    # if none use defaults

    nb = notebook.load_notebook(directory)

    directory = nb._dir

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)

    if openid is not None:
        nb.conf()['openid'] = openid
    elif not nb.conf()['openid']:
        # What is the purpose behind this elif?  It seems rather pointless.
        # all it appears to do is set the config to False if bool(config) is False
        nb.conf()['openid'] = False

    if accounts is not None:
        nb.user_manager().set_accounts(accounts)
    else:
        nb.user_manager().set_accounts(nb.conf()['accounts'])

    if nb.user_manager().user_exists('root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if nb.user_manager().user_exists('admin'):
            admin = nb.user_manager().user('admin')
            admin.set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."


    nb.upgrade_model()
    nb.save()
    del nb

    if interface != 'localhost' and not secure:
            print "*" * 70
            print "WARNING: Insecure notebook server listening on external interface."
            print "Unless you are running this via ssh port forwarding, you are"
            print "**crazy**!  You should run the notebook with the option secure=True."
            print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if automatic_login:
        "******"
    if secure:
        if (not os.path.exists(private_pem) or
            not os.path.exists(public_pem)):
            print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
            print "Now running notebook.setup()"
            notebook_setup()
        if (not os.path.exists(private_pem) or
            not os.path.exists(public_pem)):
            print "Failed to setup notebook.  Please try notebook.setup() again manually."

    kw = dict(port=port, automatic_login=automatic_login, secure=secure, private_pem=private_pem, public_pem=public_pem,
              interface=interface, directory=directory, pidfile=pidfile, cwd=cwd, profile=profile, upload = upload )
    cmd = command[server]().run_command(kw)
    if cmd is None:
        return

    if not quiet:
        print_open_msg('localhost' if not interface else interface,
        port, secure=secure)
    if secure and not quiet:
        print "There is an admin account.  If you do not remember the password,"
        print "quit the notebook and type notebook(reset=True)."
    print "Executing", cmd
    if fork:
        import pexpect
        return pexpect.spawn(cmd)
    else:
        e = os.system(cmd)

    os.chdir(cwd)
    if e == 256:
        raise socket.error
Ejemplo n.º 5
0
def notebook_twisted(
    self,
    directory=None,
    port=8000,
    address="localhost",
    port_tries=50,
    secure=False,
    reset=False,
    accounts=False,
    require_login=True,
    server_pool=None,
    ulimit=None,
    timeout=0,
    open_viewer=True,
    sagetex_path="",
    start_path="",
    fork=False,
    quiet=False,
):

    if directory is None:
        directory = "%s/sage_notebook" % DOT_SAGE
    else:
        if isinstance(directory, basestring) and len(directory) > 0 and directory[-1] == "/":
            directory = directory[:-1]

    if not os.path.exists(directory):
        os.makedirs(directory)

    if not quiet:
        print "The notebook files are stored in:", directory
    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]

    port = int(port)
    conf = "%s/twistedconf.tac" % directory

    if not secure and address != "localhost":
        print "*" * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print "*" * 70

    nb = notebook.load_notebook(directory)

    nb.conf()["idle_timeout"] = int(timeout)

    if nb.user_exists("root") and not nb.user_exists("admin"):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password("admin", "root")
        # It would be a security risk to leave an escalated account around.

    if not nb.user_exists("admin"):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if reset:
            nb.user("admin").set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        # nb.del_user('root')

    if not server_pool is None:
        nb.set_server_pool(server_pool)

    if not ulimit is None:
        nb.set_ulimit(ulimit)

    nb.set_accounts(accounts)

    if os.path.exists("%s/nb-older-backup.sobj" % directory):
        nb._migrate_worksheets()
        os.unlink("%s/nb-older-backup.sobj" % directory)
        print "Updating to new format complete."

    nb.save()
    del nb

    def run(port):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = "tls:%s:interface=%s:privateKey=%s:certKey=%s" % (port, address, private_pem, public_pem)
        else:
            strport = "tcp:%s:interface=%s" % (port, address)

        notebook_opts = '"%s",address="%s",port=%s,secure=%s' % (os.path.abspath(directory), address, port, secure)

        if open_viewer:
            if require_login:
                start_path = "'/?startup_token=%s' % startup_token"
            else:
                start_path = "'/'"
            open_page = "from sage.server.misc import open_page; open_page('%s', %s, %s, %s)" % (
                address,
                port,
                secure,
                start_path,
            )
        else:
            open_page = ""

        config = open(conf, "w")

        config.write(
            """
####################################################################
# WARNING -- Do not edit this file!   It is autogenerated each time
# the notebook(...) command is executed.
####################################################################

# Now set things up and start the notebook
import sage.server.notebook.notebook
sage.server.notebook.notebook.JSMATH=True
import sage.server.notebook.notebook as notebook
twist.notebook = notebook.load_notebook(%s)
twist.SAGETEX_PATH = "%s"
twist.OPEN_MODE = %s
twist.SID_COOKIE = str(hash("%s"))
twist.init_updates()
worksheet.init_sage_prestart(twist.notebook.get_server(), twist.notebook.get_ulimit())

def save_notebook():
    from twisted.internet.error import ReactorNotRunning
    print "Saving notebook..."
    twist.notebook.save()
    try:
        reactor.stop()
    except ReactorNotRunning:
        pass
    print "Notebook cleanly saved."

def my_sigint(x, n):
    save_notebook()
    signal.signal(signal.SIGINT, signal.SIG_DFL)


signal.signal(signal.SIGINT, my_sigint)

## Disable client-side certificate request for gnutls
try:
    import gnutls.connection
    gnutls.connection.CERT_REQUEST = 0
except OSError:
    print "Note: GNUTLS not available."


## Authentication framework (ported from Knooboo)


realm = avatars.LoginSystem()
p = portal.Portal(realm)
startup_token = '%%x' %% random.randint(0, 2**128)
startup_checker = avatars.OneTimeTokenChecker()
startup_checker.token = startup_token
p.registerChecker(startup_checker)
password_checker = avatars.PasswordChecker()
p.registerChecker(password_checker)
p.registerChecker(checkers.AllowAnonymousAccess())
rsrc = guard.MySessionWrapper(p)
log.DefaultCommonAccessLoggingObserver().start()
site = server.Site(rsrc)
factory = channel.HTTPFactory(site)

application = service.Application("SAGE Notebook")
s = strports.service('%s', factory)
%s
s.setServiceParent(application)

reactor.addSystemEventTrigger('before', 'shutdown', save_notebook)

"""
            % (notebook_opts, sagetex_path, not require_login, os.path.abspath(directory), strport, open_page)
        )

        config.close()

        ## Start up twisted
        if not quiet:
            print_open_msg("localhost" if not address else address, port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."
        cmd = 'sage -twistd --pidfile="%s"/twistd.pid -ny "%s"/twistedconf.tac' % (directory, directory)
        if fork:
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)
        if e == 256:
            raise socket.error
        return True
        # end of inner function run

    if address != "localhost" and not secure:
        print "*" * 70
        print "WARNING: Insecure notebook server listening on external address."
        print "Unless you are running this via ssh port forwarding, you are"
        print "**crazy**!  You should run the notebook with the option secure=True."
        print "*" * 70

    port = find_next_available_port(port, port_tries)
    # if open_viewer:
    #    open_page(address, port, secure, pause=PAUSE)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port)
Ejemplo n.º 6
0
def notebook_twisted(self,
                     directory=None,
                     port=8000,
                     address='localhost',
                     port_tries=50,
                     secure=False,
                     reset=False,
                     accounts=False,
                     require_login=True,
                     server_pool=None,
                     ulimit=None,
                     timeout=0,
                     open_viewer=True,
                     sagetex_path="",
                     start_path="",
                     fork=False,
                     quiet=False):

    if directory is None:
        directory = '%s/sage_notebook' % DOT_SAGE
    else:
        if isinstance(
                directory,
                basestring) and len(directory) > 0 and directory[-1] == "/":
            directory = directory[:-1]

    if not os.path.exists(directory):
        os.makedirs(directory)

    if not quiet:
        print "The notebook files are stored in:", directory
    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]: os.chdir(wd[0])
    directory = wd[1]

    port = int(port)
    conf = '%s/twistedconf.tac' % directory

    if not secure and address != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    nb = notebook.load_notebook(directory)

    nb.conf()['idle_timeout'] = int(timeout)

    if nb.user_exists('root') and not nb.user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if reset:
            nb.user('admin').set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    if not server_pool is None:
        nb.set_server_pool(server_pool)

    if not ulimit is None:
        nb.set_ulimit(ulimit)

    nb.set_accounts(accounts)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."

    nb.save()
    del nb

    def run(port):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(
                    public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(
                    public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = 'tls:%s:interface=%s:privateKey=%s:certKey=%s' % (
                port, address, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, address)

        notebook_opts = '"%s",address="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), address, port, secure)

        if open_viewer:
            if require_login:
                start_path = "'/?startup_token=%s' % startup_token"
            else:
                start_path = "'/'"
            open_page = "from sage.server.misc import open_page; open_page('%s', %s, %s, %s)" % (
                address, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        config.write("""
####################################################################
# WARNING -- Do not edit this file!   It is autogenerated each time
# the notebook(...) command is executed.
####################################################################

# Now set things up and start the notebook
import sage.server.notebook.notebook
sage.server.notebook.notebook.JSMATH=True
import sage.server.notebook.notebook as notebook
twist.notebook = notebook.load_notebook(%s)
twist.SAGETEX_PATH = "%s"
twist.OPEN_MODE = %s
twist.SID_COOKIE = str(hash("%s"))
twist.init_updates()
worksheet.init_sage_prestart(twist.notebook.get_server(), twist.notebook.get_ulimit())

def save_notebook():
    from twisted.internet.error import ReactorNotRunning
    print "Saving notebook..."
    twist.notebook.save()
    try:
        reactor.stop()
    except ReactorNotRunning:
        pass
    print "Notebook cleanly saved."

def my_sigint(x, n):
    save_notebook()
    signal.signal(signal.SIGINT, signal.SIG_DFL)

signal.signal(signal.SIGINT, my_sigint)

## Disable client-side certificate request for gnutls
try:
    import gnutls.connection
    gnutls.connection.CERT_REQUEST = 0
except OSError:
    print "Note: GNUTLS not available."

## Authentication framework (ported from Knooboo)

realm = avatars.LoginSystem()
p = portal.Portal(realm)
startup_token = '%%x' %% random.randint(0, 2**128)
startup_checker = avatars.OneTimeTokenChecker()
startup_checker.token = startup_token
p.registerChecker(startup_checker)
password_checker = avatars.PasswordChecker()
p.registerChecker(password_checker)
p.registerChecker(checkers.AllowAnonymousAccess())
rsrc = guard.MySessionWrapper(p)
log.DefaultCommonAccessLoggingObserver().start()
site = server.Site(rsrc)
factory = channel.HTTPFactory(site)

application = service.Application("SAGE Notebook")
s = strports.service('%s', factory)
%s
s.setServiceParent(application)

reactor.addSystemEventTrigger('before', 'shutdown', save_notebook)

""" % (notebook_opts, sagetex_path, not require_login,
        os.path.abspath(directory), strport, open_page))

        config.close()

        ## Start up twisted
        if not quiet:
            print_open_msg('localhost' if not address else address,
                           port,
                           secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."
        cmd = 'sage -twistd --pidfile="%s"/twistd.pid -ny "%s"/twistedconf.tac' % (
            directory, directory)
        if fork:
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)
        if e == 256:
            raise socket.error
        return True
        # end of inner function run

    if address != 'localhost' and not secure:
        print "*" * 70
        print "WARNING: Insecure notebook server listening on external address."
        print "Unless you are running this via ssh port forwarding, you are"
        print "**crazy**!  You should run the notebook with the option secure=True."
        print "*" * 70

    port = find_next_available_port(port, port_tries)
    #if open_viewer:
    #    open_page(address, port, secure, pause=PAUSE)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port)
Ejemplo n.º 7
0
def notebook_run(
    self,
    directory=None,
    port=8080,
    interface='localhost',
    port_tries=50,
    secure=False,
    reset=False,
    accounts=None,
    openid=None,
    server_pool=None,
    ulimit='',
    timeout=None,  # timeout for normal worksheets. This is the
    # same as idle_timeout in server_conf.py
    doc_timeout=None,  # timeout for documentation worksheets
    upload=None,
    automatic_login=True,
    start_path="",
    fork=False,
    quiet=False,
    server="twistd",
    profile=False,
    subnets=None,
    require_login=None,
    open_viewer=None,
    address=None,
):

    # Check whether pyOpenSSL is installed or not (see Sage trac #13385)
    if secure:
        try:
            import OpenSSL
        except ImportError:
            raise RuntimeError(
                "HTTPS cannot be used without pyOpenSSL"
                " installed. See the Sage README for more information.")

    # Turn it into a full path for later conversion to a file URL
    if upload:
        upload_abs = os.path.abspath(upload)
        if os.path.exists(upload_abs):
            upload = upload_abs
        else:
            # They might have expected ~ to be expanded to their user directory
            upload = os.path.expanduser(upload)
            if not os.path.exists(upload):
                raise ValueError("Unable to find the file %s to upload" %
                                 upload)

    if subnets is not None:
        raise ValueError(
            """The subnets parameter is no longer supported. Please use a firewall to block subnets, or even better, volunteer to write the code to implement subnets again."""
        )
    if require_login is not None or open_viewer is not None:
        raise ValueError(
            "The require_login and open_viewer parameters are no longer supported.  "
            "Please use automatic_login=True to automatically log in as admin, "
            "or use automatic_login=False to not automatically log in.")
    if address is not None:
        raise ValueError(
            "Use 'interface' instead of 'address' when calling notebook(...).")

    cwd = os.getcwd()

    if directory is None:
        directory = '%s/sage_notebook.sagenb' % DOT_SAGENB
    else:
        directory = directory.rstrip('/')
        if not directory.endswith('.sagenb'):
            directory += '.sagenb'

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]
    pidfile = os.path.join(directory, 'sagenb.pid')

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    # first use provided values, if none, use loaded values,
    # if none use defaults

    nb = notebook.load_notebook(directory)

    directory = nb._dir

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    if timeout is not None:
        nb.conf()['idle_timeout'] = int(timeout)
    if doc_timeout is not None:
        nb.conf()['doc_timeout'] = int(doc_timeout)

    if openid is not None:
        nb.conf()['openid'] = openid
    elif not nb.conf()['openid']:
        # What is the purpose behind this elif?  It seems rather pointless.
        # all it appears to do is set the config to False if bool(config) is False
        nb.conf()['openid'] = False

    if accounts is not None:
        nb.user_manager().set_accounts(accounts)
    else:
        nb.user_manager().set_accounts(nb.conf()['accounts'])

    if nb.user_manager().user_exists(
            'root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if nb.user_manager().user_exists('admin'):
            admin = nb.user_manager().user('admin')
            admin.set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    # For old notebooks, make sure that default users are always created.
    # This fixes issue #175 (https://github.com/sagemath/sagenb/issues/175)
    um = nb.user_manager()
    for user in ('_sage_', 'pub'):
        if not um.user_exists(user):
            um.add_user(user, '', '', account_type='user', force=True)
    if not um.user_exists('guest'):
        um.add_user('guest', '', '', account_type='guest', force=True)

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."

    nb.upgrade_model()
    nb.save()
    del nb

    if interface != 'localhost' and not secure:
        print "*" * 70
        print "WARNING: Insecure notebook server listening on external interface."
        print "Unless you are running this via ssh port forwarding, you are"
        print "**crazy**!  You should run the notebook with the option secure=True."
        print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if automatic_login:
        "******"
    if secure:
        if (not os.path.exists(private_pem) or not os.path.exists(public_pem)):
            print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
            print "Now running notebook.setup()"
            notebook_setup()
        if (not os.path.exists(private_pem) or not os.path.exists(public_pem)):
            print "Failed to setup notebook.  Please try notebook.setup() again manually."

    kw = dict(port=port,
              automatic_login=automatic_login,
              secure=secure,
              private_pem=private_pem,
              public_pem=public_pem,
              interface=interface,
              directory=directory,
              pidfile=pidfile,
              cwd=cwd,
              profile=profile,
              upload=upload)
    cmd = command[server]().run_command(kw)
    if cmd is None:
        return

    if not quiet:
        print_open_msg('localhost' if not interface else interface,
                       port,
                       secure=secure)
    if secure and not quiet:
        print "There is an admin account.  If you do not remember the password,"
        print "quit the notebook and type notebook(reset=True)."
    print "Executing", cmd
    if fork:
        import pexpect
        return pexpect.spawn(cmd)
    else:
        e = os.system(cmd)

    os.chdir(cwd)
    if e == 256:
        raise socket.error
Ejemplo n.º 8
0
def notebook_twisted(self,
             directory     = None,
             port          = 8080,
             interface     = 'localhost',        
             address       = None,
             port_tries    = 50,
             secure        = False,
             reset         = False,
             require_login = True, 
             accounts      = None,
             openid        = None,
                     
             server_pool   = None,
             ulimit        = '',

             timeout       = 0,

             open_viewer   = True,

             sagetex_path  = "",
             start_path    = "",
             fork          = False,
             quiet         = False,
             subnets = None):

    if subnets is not None:
        raise ValueError("""The subnets parameter is no longer supported. Please use a firewall to block subnets, or even better, volunteer to write the code to implement subnets again.""")

    cwd = os.getcwd()
    # For backwards compatible, we still allow the address to be set
    # instead of the interface argument
    if address is not None:
        from warnings import warn
        message = "Use 'interface' instead of 'address' when calling notebook(...)."
        warn(message, DeprecationWarning, stacklevel=3)
        interface = address

    if directory is None:
        directory = '%s/sage_notebook' % DOT_SAGENB
    else:
        if (isinstance(directory, basestring) and len(directory) > 0 and
           directory[-1] == "/"):
            directory = directory[:-1]

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    # first use provided values, if none, use loaded values, 
    # if none use defaults

    nb = notebook.load_notebook(directory)
    
    directory = nb._dir
    conf = os.path.join(directory, 'twistedconf.tac')
    
    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)
    nb.conf()['require_login'] = require_login

    if openid is not None:
        nb.conf()['openid'] = openid 
    elif not nb.conf()['openid']:
        nb.conf()['openid'] = False

    if accounts is not None:
        nb.user_manager().set_accounts(accounts)
    elif not nb.conf()['accounts']:
        nb.user_manager().set_accounts(True)
    
    if nb.user_manager().user_exists('root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True
        
    if reset:
        passwd = get_admin_passwd()                
        if reset:
            admin = nb.user_manager().user('admin')
            admin.set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')
            
    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)
    
    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."


    nb.upgrade_model()

    nb.save()
    del nb

    def run(port):
        # Is a server already running? Check if a Twistd PID exists in
        # the given directory.
        pidfile = os.path.join(directory, 'twistd.pid')
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())

                if str(e).startswith('Another twistd server is running,'):
                    print 'Another Sage Notebook server is running, PID %d.' % pid
                    old_interface, old_port, old_secure = get_old_settings(conf)
                    if open_viewer and old_port:
                        old_interface = old_interface or 'localhost'

                        print 'Opening web browser at http%s://%s:%s/ ...' % (
                            's' if old_secure else '', old_interface, old_port)

                        from sagenb.misc.misc import open_page as browse_to
                        browse_to(old_interface, old_port, old_secure, '/')
                        return
                    print '\nPlease either stop the old server or run the new server in a different directory.'
                    return

        ## Create the config file
        if secure:
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s'%(
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        config.write(FLASK_NOTEBOOK_CONFIG%{'notebook_opts': notebook_opts, 'sagetex_path': sagetex_path,
                                            'do_not_require_login': not require_login,
                                            'dir': os.path.abspath(directory), 'cwd':cwd, 
                                            'strport': strport,
                                            'open_page': open_page})


        config.close()                     

        ## Start up twisted
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, conf)
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
            port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
        # end of inner function run
                     
    if interface != 'localhost' and not secure:
            print "*" * 70
            print "WARNING: Insecure notebook server listening on external interface."
            print "Unless you are running this via ssh port forwarding, you are"
            print "**crazy**!  You should run the notebook with the option secure=True."
            print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port)
Ejemplo n.º 9
0
def notebook_twisted(self,
             directory   = None,
             port        = 8000,
             interface   = 'localhost',        
             address     = None,
             port_tries  = 50,
             secure      = False,
             reset       = False,
             accounts    = False,
             require_login = True, 
                     
             server_pool = None,
             ulimit      = '',

             timeout     = 0,

             open_viewer = True,

             sagetex_path = "",
             start_path = "",
             fork = False,
             quiet = False,

             subnets = None):

    cwd = os.getcwd()
    # For backwards compatible, we still allow the address to be set
    # instead of the interface argument
    if address is not None:
        from warnings import warn
        message = "Use 'interface' instead of 'address' when calling notebook(...)."
        warn(message, DeprecationWarning, stacklevel=3)
        interface = address
             
    if directory is None:
        directory = '%s/sage_notebook'%DOT_SAGENB
    else:
        if isinstance(directory, basestring) and len(directory) > 0 and directory[-1] == "/":
            directory = directory[:-1]
            
    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]: os.chdir(wd[0])
    directory = wd[1]

    port = int(port)

    if not secure and interface != 'localhost':
        print '*'*70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*'*70

    nb = notebook.load_notebook(directory)
    
    directory = nb._dir
    conf = os.path.join(directory, 'twistedconf.tac')
    
    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)
    nb.conf()['require_login'] = require_login
    
    if nb.user_manager().user_exists('root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook. 
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around. 

    if not nb.user_manager().user_exists('admin'):
        reset = True
        
    if reset:  
        passwd = get_admin_passwd()                
        if reset:
            nb.user_manager().user('admin').set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*"*70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')  
            
    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)
    nb.user_manager().set_accounts(accounts)
    
    if os.path.exists('%s/nb-older-backup.sobj'%directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj'%directory)
        print "Updating to new format complete."

    nb.save()
    del nb

    def run(port, subnets):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s'%(protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s'%(port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (os.path.abspath(directory),
                interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)"%(hostname, port, secure, start_path)
        else:
            open_page = ''
        
        config = open(conf, 'w')

        if subnets is None:
            factory = "factory = channel.HTTPFactory(site)"
        else:
            if not isinstance(subnets, (list, tuple)):
                subnets = [subnets]
            factory = """
# See http://stackoverflow.com/questions/1273297/python-twisted-restricting-access-by-ip-address
from sagenb.misc.ipaddr import IPNetwork
subnets = eval(r"%s")
if not any(s.startswith('127') for s in subnets):
    subnets.insert(0, '127.0.0.0/8')
subnets = [IPNetwork(x) for x in subnets]
class RestrictedIPFactory(channel.HTTPFactory):
    def buildProtocol(self, addr):
        a = str(addr.host)
        for X in subnets:
            if a in X:
                return channel.HTTPFactory.buildProtocol(self, addr)
        print 'Ignoring all requests from IP address '+str(addr.host)
        
factory = RestrictedIPFactory(site)
"""%tuple([subnets])

        config.write(FLASK_NOTEBOOK_CONFIG%{'notebook_opts': notebook_opts, 'sagetex_path': sagetex_path,
                                            'do_not_require_login': not require_login,
                                            'dir': os.path.abspath(directory), 'cwd':cwd, 
                                            'factory': factory, 'strport': strport,
                                            'open_page': open_page})


        config.close()                     

        pidfile = os.path.join(directory, 'twistd.pid')
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, os.path.join(directory, 'twistedconf.tac'))

        # Check if a Twistd PID exists in the given directory
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())
                if str(e).startswith('Another twistd server is running,'):
                    sys.exit("""\
Another Sage Notebook server is running, PID %d.

Please either stop the old server or run the new server in a different directory.
""" % pid)
        ## Start up twisted
        if not quiet:
            print_open_msg('localhost' if not interface else interface, port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
        # end of inner function run
                     
    if interface != 'localhost' and not secure:
            print "*"*70
            print "WARNING: Insecure notebook server listening on external interface."
            print "Unless you are running this via ssh port forwarding, you are"
            print "**crazy**!  You should run the notebook with the option secure=True."
            print "*"*70

    port = find_next_available_port(interface, port, port_tries)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port, subnets)
Ejemplo n.º 10
0
def notebook_twisted(self,
                     directory=None,
                     port=8000,
                     interface='localhost',
                     address=None,
                     port_tries=50,
                     secure=False,
                     reset=False,
                     accounts=False,
                     require_login=True,
                     server_pool=None,
                     ulimit='',
                     timeout=0,
                     open_viewer=True,
                     sagetex_path="",
                     start_path="",
                     fork=False,
                     quiet=False,
                     subnets=None):

    cwd = os.getcwd()
    # For backwards compatible, we still allow the address to be set
    # instead of the interface argument
    if address is not None:
        from warnings import warn
        message = "Use 'interface' instead of 'address' when calling notebook(...)."
        warn(message, DeprecationWarning, stacklevel=3)
        interface = address

    if directory is None:
        directory = '%s/sage_notebook' % DOT_SAGENB
    else:
        if isinstance(
                directory,
                basestring) and len(directory) > 0 and directory[-1] == "/":
            directory = directory[:-1]

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]: os.chdir(wd[0])
    directory = wd[1]

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    nb = notebook.load_notebook(directory)

    directory = nb._dir
    conf = os.path.join(directory, 'twistedconf.tac')

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)
    nb.conf()['require_login'] = require_login

    if nb.user_manager().user_exists(
            'root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if reset:
            nb.user_manager().user('admin').set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)
    nb.user_manager().set_accounts(accounts)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."

    nb.save()
    del nb

    def run(port, subnets):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(
                    public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(
                    public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s' % (
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (
                hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        if subnets is None:
            factory = "factory = channel.HTTPFactory(site)"
        else:
            if not isinstance(subnets, (list, tuple)):
                subnets = [subnets]
            factory = """
# See http://stackoverflow.com/questions/1273297/python-twisted-restricting-access-by-ip-address
from sagenb.misc.ipaddr import IPNetwork
subnets = eval(r"%s")
if not any(s.startswith('127') for s in subnets):
    subnets.insert(0, '127.0.0.0/8')
subnets = [IPNetwork(x) for x in subnets]
class RestrictedIPFactory(channel.HTTPFactory):
    def buildProtocol(self, addr):
        a = str(addr.host)
        for X in subnets:
            if a in X:
                return channel.HTTPFactory.buildProtocol(self, addr)
        print 'Ignoring all requests from IP address '+str(addr.host)
        
factory = RestrictedIPFactory(site)
""" % tuple([subnets])

        config.write(
            FLASK_NOTEBOOK_CONFIG % {
                'notebook_opts': notebook_opts,
                'sagetex_path': sagetex_path,
                'do_not_require_login': not require_login,
                'dir': os.path.abspath(directory),
                'cwd': cwd,
                'factory': factory,
                'strport': strport,
                'open_page': open_page
            })

        config.close()

        pidfile = os.path.join(directory, 'twistd.pid')
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (
            pidfile, os.path.join(directory, 'twistedconf.tac'))

        # Check if a Twistd PID exists in the given directory
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())
                if str(e).startswith('Another twistd server is running,'):
                    sys.exit("""\
Another Sage Notebook server is running, PID %d.

Please either stop the old server or run the new server in a different directory.
""" % pid)
        ## Start up twisted
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
                           port,
                           secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
        # end of inner function run

    if interface != 'localhost' and not secure:
        print "*" * 70
        print "WARNING: Insecure notebook server listening on external interface."
        print "Unless you are running this via ssh port forwarding, you are"
        print "**crazy**!  You should run the notebook with the option secure=True."
        print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port, subnets)
Ejemplo n.º 11
0
def notebook_twisted(self,
                     directory=None,
                     port=8000,
                     interface='localhost',
                     address=None,
                     port_tries=50,
                     secure=False,
                     reset=False,
                     require_login=True,
                     accounts=None,
                     openid=None,
                     server_pool=None,
                     ulimit='',
                     timeout=0,
                     open_viewer=True,
                     sagetex_path="",
                     start_path="",
                     fork=False,
                     quiet=False,
                     subnets=None):

    if subnets is not None:
        raise ValueError(
            """The subnets parameter is no longer supported. Please use a firewall to block subnets, or even better, volunteer to write the code to implement subnets again."""
        )

    cwd = os.getcwd()
    # For backwards compatible, we still allow the address to be set
    # instead of the interface argument
    if address is not None:
        from warnings import warn
        message = "Use 'interface' instead of 'address' when calling notebook(...)."
        warn(message, DeprecationWarning, stacklevel=3)
        interface = address

    if directory is None:
        directory = '%s/sage_notebook' % DOT_SAGENB
    else:
        if (isinstance(directory, basestring) and len(directory) > 0
                and directory[-1] == "/"):
            directory = directory[:-1]

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    # first use provided values, if none, use loaded values,
    # if none use defaults

    nb = notebook.load_notebook(directory)

    directory = nb._dir
    conf = os.path.join(directory, 'twistedconf.tac')

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)
    nb.conf()['require_login'] = require_login

    if openid is not None:
        nb.conf()['openid'] = openid
    elif not nb.conf()['openid']:
        nb.conf()['openid'] = False

    if accounts is not None:
        nb.user_manager().set_accounts(accounts)
    elif not nb.conf()['accounts']:
        nb.user_manager().set_accounts(True)

    if nb.user_manager().user_exists(
            'root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if reset:
            admin = nb.user_manager().user('admin')
            admin.set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."

    nb.upgrade_model()

    nb.save()
    del nb

    def run(port):
        # Is a server already running? Check if a Twistd PID exists in
        # the given directory.
        pidfile = os.path.join(directory, 'twistd.pid')
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())

                if str(e).startswith('Another twistd server is running,'):
                    print 'Another Sage Notebook server is running, PID %d.' % pid
                    old_interface, old_port, old_secure = get_old_settings(
                        conf)
                    if open_viewer and old_port:
                        old_interface = old_interface or 'localhost'

                        print 'Opening web browser at http%s://%s:%s/ ...' % (
                            's' if old_secure else '', old_interface, old_port)

                        from sagenb.misc.misc import open_page as browse_to
                        browse_to(old_interface, old_port, old_secure, '/')
                        return
                    print '\nPlease either stop the old server or run the new server in a different directory.'
                    return

        ## Create the config file
        if secure:
            if (not os.path.exists(private_pem)
                    or not os.path.exists(public_pem)):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if (not os.path.exists(private_pem)
                    or not os.path.exists(public_pem)):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s' % (
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (
                hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        config.write(
            FLASK_NOTEBOOK_CONFIG % {
                'notebook_opts': notebook_opts,
                'sagetex_path': sagetex_path,
                'do_not_require_login': not require_login,
                'dir': os.path.abspath(directory),
                'cwd': cwd,
                'strport': strport,
                'open_page': open_page
            })

        config.close()

        ## Start up twisted
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, conf)
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
                           port,
                           secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
        # end of inner function run

    if interface != 'localhost' and not secure:
        print "*" * 70
        print "WARNING: Insecure notebook server listening on external interface."
        print "Unless you are running this via ssh port forwarding, you are"
        print "**crazy**!  You should run the notebook with the option secure=True."
        print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if open_viewer:
        "Open viewer automatically isn't fully implemented.  You have to manually open your web browser to the above URL."
    return run(port)