Clean-up and improvements on twisted.manhole

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1086 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-02-18 15:53:34 +00:00
parent 98ce9acb56
commit 72a3d7cf2c

View file

@ -1,14 +1,37 @@
"""
A simple twisted manhole that allows you to access a running Zope 3
instance via a python command line without having to run ZEO.
You may run it for testing purposes via `python manhole.py` (note that
the twisted library must be reachable via your PYTHONPATH) and log in
from another console window using `ssh -p 5001 admin@localhost`. The
password is defined below in the "reactor.listenTCP()" statement. The
manhole script may be stopped with Ctrl-C.
Note that this will open up a serious security hole on your computer
as now anybody knowing this password may login to the Python console
and get full access to the system with the permissions of the user
running the manhole script.
In order to use it with Zope copy the cybertools.twisted-configure.zcml
to the etc/package-includes directory of your Zope instance and restart
Zope. You can then log in with ssh like shown above, using the username
and password of the zope.manager principal defined in your principals.zcml.
After logging in use the `help` command to get more information.
$Id$
"""
from twisted.internet import reactor, protocol
from twisted.internet import reactor, protocol, defer
from twisted.protocols import basic
from twisted.cred import portal, checkers
from twisted.cred import portal, checkers, credentials, error as credError
from twisted.conch import manhole, manhole_ssh
from zope.interface import implements
try:
from zope.app.publication.zopepublication import ZopePublication
from zope.app.component.hooks import setSite
from zope.app.security.principalregistry import principalRegistry
from zope.app import zapi
hasZope = True
except:
@ -17,34 +40,60 @@ import time
import sys
from cStringIO import StringIO
def getManholeFactory(namespace, **passwords):
realm = manhole_ssh.TerminalRealm()
def getManhole(_):
return manhole.Manhole(namespace)
realm.chainedProtocolFactory.protocolFactory = getManhole
p = portal.Portal(realm)
p.registerChecker(
checkers.InMemoryUsernamePasswordDatabaseDontUse(**passwords))
checker = (hasZope and ZopeManagerChecker() or
checkers.InMemoryUsernamePasswordDatabaseDontUse(**passwords))
p.registerChecker(checker)
return manhole_ssh.ConchFactory(p)
class ZopeManagerChecker(object):
implements(checkers.ICredentialsChecker)
credentialInterfaces = (credentials.IUsernamePassword,)
def requestAvatarId(self, credentials):
manager = principalRegistry.getPrincipal('zope.manager')
login = credentials.username
password = credentials.password
if login == manager.getLogin() and manager.validate(password):
return defer.succeed(login)
return defer.fail(credError.UnauthorizedLogin(
'User/password not correct'))
def printTime():
print 'twisted.manhole running:', time.strftime('%H:%M:%S')
reactor.callLater(60, printTime)
def help():
info = """
Use dir() to see what variables and functions are available."""
zopeInfo = """
In order to get access to local utilities and adapters you should
issue a setSite(root). Don't forget to call setSite() before
finishing your session.
You may use x = zapi.traverse(root, 'path/to/object') to get an
object in your folder hierarchy. Then you may call any method or
access any attribute of this object."""
print info
if hasZope:
print zopeInfo
print
class Help(object):
def __repr__(self):
info = """
Use dir() to see what variables and functions are available.
"""
zopeInfo = """
You may use x = zapi.traverse(root, 'path/to/object') to get an
object in your folder hierarchy. Then you may call any method or
access any attribute of this object.
In order to get access to local utilities and adapters you may
issue a setSite(root). Don't forget to call setSite() before
finishing your session in order to reset this setting.
"""
return info + (hasZope and zopeInfo or '')
def __call__(self):
print self
help = Help()
def startup(event=None, port=5001):
@ -52,14 +101,14 @@ def startup(event=None, port=5001):
printTime()
d = globals()
if hasZope and event is not None:
conn =event.database.open()
root = conn.root()[ZopePublication.root_name]
connection = event.database.open()
root = connection.root()[ZopePublication.root_name]
else:
hasZope = False
d.update(locals())
namespace = {}
for key in ('__builtins__', 'conn', 'event', 'setSite', 'hasZope', 'zapi',
'root', '__doc__', 'help'):
for key in ('__builtins__', 'connection', 'event', 'setSite', 'hasZope',
'zapi', 'root', '__doc__', 'help'):
if key in d:
namespace[key] = d[key]
# TODO: get admin password from somewhere else or use a real checker.