~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/codehosting/sshserver/service.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2010-04-16 22:37:59 UTC
  • mfrom: (10693.3.32 extract-ssh-server-auth)
  • Revision ID: launchpad@pqm.canonical.com-20100416223759-nimb88k917yijz02
[r=intellectronica][ui=none] Move codehosting-specific stuff into new
        codehosting-specific module

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
    ]
13
13
 
14
14
 
 
15
import logging
15
16
import os
16
17
 
17
18
from twisted.application import service, strports
20
21
from twisted.conch.ssh.transport import SSHServerTransport
21
22
from twisted.internet import defer
22
23
from twisted.protocols.policies import TimeoutFactory
23
 
from twisted.web.xmlrpc import Proxy
24
24
 
25
25
from zope.event import notify
26
26
 
27
 
from canonical.config import config
28
 
from lp.codehosting.sshserver import accesslog
29
 
from lp.codehosting.sshserver.auth import get_portal, SSHUserAuthServer
 
27
from lp.codehosting.sshserver import accesslog, events
 
28
from lp.codehosting.sshserver.auth import SSHUserAuthServer
30
29
from lp.services.twistedsupport import gatherResults
31
 
 
32
 
 
33
 
# The names of the key files of the server itself. The directory itself is
34
 
# given in config.codehosting.host_key_pair_path.
35
 
PRIVATE_KEY_FILE = 'ssh_host_key_rsa'
36
 
PUBLIC_KEY_FILE = 'ssh_host_key_rsa.pub'
 
30
from lp.services.twistedsupport.loggingsupport import set_up_oops_reporting
37
31
 
38
32
 
39
33
class KeepAliveSettingSSHServerTransport(SSHServerTransport):
43
37
        self.transport.setTcpKeepAlive(True)
44
38
 
45
39
 
46
 
def get_key_path(key_filename):
47
 
    key_directory = config.codehosting.host_key_pair_path
48
 
    return os.path.join(config.root, key_directory, key_filename)
49
 
 
50
 
 
51
 
def make_portal():
52
 
    """Create and return a `Portal` for the SSH service.
53
 
 
54
 
    This portal accepts SSH credentials and returns our customized SSH
55
 
    avatars (see `lp.codehosting.sshserver.auth.LaunchpadAvatar`).
56
 
    """
57
 
    authentication_proxy = Proxy(
58
 
        config.codehosting.authentication_endpoint)
59
 
    branchfs_proxy = Proxy(config.codehosting.branchfs_endpoint)
60
 
    return get_portal(authentication_proxy, branchfs_proxy)
61
 
 
62
 
 
63
 
 
64
40
class Factory(SSHFactory):
65
 
    """SSH factory that uses the codehosting custom authentication.
 
41
    """SSH factory that uses Launchpad's custom authentication.
66
42
 
67
43
    This class tells the SSH service to use our custom authentication service
68
44
    and configures the host keys for the SSH server. It also logs connection
105
81
        transport._realConnectionLost = transport.connectionLost
106
82
        transport.connectionLost = (
107
83
            lambda reason: self.connectionLost(transport, reason))
108
 
        notify(accesslog.UserConnected(transport, address))
 
84
        notify(events.UserConnected(transport, address))
109
85
        return transport
110
86
 
111
87
    def connectionLost(self, transport, reason):
124
100
            # b) the server doesn't normally generate a "go away" event.
125
101
            # Rather, the client simply stops trying.
126
102
            if getattr(transport, 'avatar', None) is None:
127
 
                notify(accesslog.AuthenticationFailed(transport))
128
 
            notify(accesslog.UserDisconnected(transport))
 
103
                notify(events.AuthenticationFailed(transport))
 
104
            notify(events.UserDisconnected(transport))
129
105
 
130
106
    def getPublicKeys(self):
131
107
        """Return the server's configured public key.
143
119
 
144
120
 
145
121
class SSHService(service.Service):
146
 
    """A Twisted service for the codehosting SSH server."""
 
122
    """A Twisted service for the SSH server."""
147
123
 
148
124
    def __init__(self, portal, private_key_path, public_key_path,
149
 
                 strport='tcp:22', idle_timeout=3600, banner=None):
 
125
                 oops_configuration, main_log, access_log,
 
126
                 access_log_path, strport='tcp:22', idle_timeout=3600,
 
127
                 banner=None):
150
128
        """Construct an SSH service.
151
129
 
152
130
        :param portal: The `Portal` that turns authentication requests into
153
131
            views on the system.
154
132
        :param private_key_path: The path to the SSH server's private key.
155
133
        :param public_key_path: The path to the SSH server's public key.
 
134
        :param oops_configuration: The section of the configuration file with
 
135
            the OOPS config details for this server.
 
136
        :param main_log: A `logging.Logger` object to log most of the server
 
137
            stuff to.
 
138
        :param access_log: A `logging.Logger` object to log the server access
 
139
            details to.
 
140
        :param access_log_path: The path to the access log file.
156
141
        :param strport: The port to run the server on, expressed in Twisted's
157
142
            "strports" mini-language. Defaults to 'tcp:22'.
158
143
        :param idle_timeout: The number of seconds to wait before killing a
168
153
                banner=banner),
169
154
            timeoutPeriod=idle_timeout)
170
155
        self.service = strports.service(strport, ssh_factory)
 
156
        self._oops_configuration = oops_configuration
 
157
        self._main_log = main_log
 
158
        self._access_log = access_log
 
159
        self._access_log_path = access_log_path
171
160
 
172
161
    def startService(self):
173
162
        """Start the SSH service."""
174
 
        accesslog.LoggingManager().setUp(configure_oops_reporting=True)
175
 
        notify(accesslog.ServerStarting())
 
163
        manager = accesslog.LoggingManager(
 
164
            logging.getLogger(self._main_log),
 
165
            logging.getLogger(self._access_log_path),
 
166
            self._access_log_path)
 
167
        manager.setUp()
 
168
        set_up_oops_reporting(self._oops_configuration)
 
169
        notify(events.ServerStarting())
176
170
        # By default, only the owner of files should be able to write to them.
177
171
        # Perhaps in the future this line will be deleted and the umask
178
172
        # managed by the startup script.
186
180
            defer.maybeDeferred(service.Service.stopService, self),
187
181
            defer.maybeDeferred(self.service.stopService)])
188
182
        def log_stopped(ignored):
189
 
            notify(accesslog.ServerStopped())
 
183
            notify(events.ServerStopped())
190
184
            return ignored
191
185
        return deferred.addBoth(log_stopped)