Skip to content

Commit 4a91943

Browse files
committed
CHECKPOINT: running coreapi server
1 parent f0c8290 commit 4a91943

File tree

4 files changed

+62
-203
lines changed

4 files changed

+62
-203
lines changed

mig/services/coreapi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from mig.services.coreapi.server import ThreadedApiHttpServer, _extend_configuration, _create_and_expose_server
1+
from mig.services.coreapi.server import ThreadedApiHttpServer, _create_and_expose_server

mig/services/coreapi/__main__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from argparse import ArgumentError
2+
import sys
3+
4+
from mig.shared.arguments import parse_getopt_args
5+
from mig.shared.conf import get_configuration_object
6+
from mig.services.coreapi.server import main as server_main
7+
8+
9+
def _required_argument_error(option, argument_name):
10+
raise ArgumentError('Missing required argument: %s %s' %
11+
(option, argument_name.upper()))
12+
13+
14+
if __name__ == '__main__':
15+
(opts, args) = parse_getopt_args(sys.argv[1:], 'c:')
16+
17+
if 'c' not in opts:
18+
raise _required_argument_error('-c', 'config_file')
19+
20+
configuration = get_configuration_object(opts.c)
21+
server_main(configuration)

mig/services/coreapi/server.py

Lines changed: 26 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -193,50 +193,15 @@ class ApiHttpServer(HTTPServer):
193193
# any gain and it potentially introduces a race
194194
hash_cache, scramble_cache = None, None
195195

196-
def __init__(self, configuration, **kwargs):
196+
def __init__(self, configuration, logger=None, host=None, port=None, **kwargs):
197197
self.configuration = configuration
198-
self.logger = configuration.logger
198+
self.logger = logger if logger else configuration.logger
199+
self.server_app = None
199200
self._on_start = kwargs.pop('on_start', lambda _: None)
200201

201-
address = configuration.daemon_conf['address']
202-
port = configuration.daemon_conf['port']
203-
204-
addr = (address, port)
202+
addr = (host, port)
205203
HTTPServer.__init__(self, addr, ApiHttpRequestHandler, **kwargs)
206204

207-
fqdn = self.server_name
208-
port = self.server_port
209-
# Masquerading if needed
210-
if configuration.daemon_conf['show_address']:
211-
fqdn = configuration.daemon_conf['show_address']
212-
if configuration.daemon_conf['show_port']:
213-
port = configuration.daemon_conf['show_port']
214-
if configuration.daemon_conf['nossl']:
215-
proto = 'http'
216-
proto_port = 80
217-
else:
218-
proto = 'https'
219-
proto_port = 443
220-
if port != proto_port:
221-
self.base_url = '%s://%s:%s/' % (proto, fqdn, port)
222-
else:
223-
self.base_url = '%s://%s/' % (proto, fqdn)
224-
225-
# We serve from sub dir to ease targeted proxying
226-
self.server_app = None
227-
self.server_base = 'openid'
228-
self.base_url += "%s/" % self.server_base
229-
self.openid = None
230-
self.approved = {}
231-
self.lastCheckIDRequest = {}
232-
233-
# print "DEBUG: sreg fields: %s" % sreg.data_fields
234-
for name in cert_field_names:
235-
cert_field_aliases[name] = []
236-
for target in [i for i in cert_field_names if name != i]:
237-
if cert_field_map[name] == cert_field_map[target]:
238-
cert_field_aliases[name].append(target)
239-
240205
@property
241206
def base_environ(self):
242207
return {}
@@ -263,7 +228,11 @@ def server_activate(self):
263228

264229
class ThreadedApiHttpServer(ThreadingMixIn, ApiHttpServer):
265230
"""Multi-threaded version of the ApiHttpServer"""
266-
pass
231+
232+
@property
233+
def base_url(self):
234+
proto = 'http'
235+
return '%s://%s:%d/' % (proto, self.server_name, self.server_port)
267236

268237

269238
class ApiHttpRequestHandler(WSGIRequestHandler):
@@ -311,11 +280,6 @@ class ApiHttpRequestHandler(WSGIRequestHandler):
311280
def __init__(self, socket, addr, server, **kwargs):
312281
self.server = server
313282

314-
if self.daemon_conf['session_ttl'] > 0:
315-
self.session_ttl = self.daemon_conf['session_ttl']
316-
else:
317-
self.session_ttl = 48 * 3600
318-
319283
# NOTE: drop idle clients after N seconds to clean stale connections.
320284
# Does NOT include clients that connect and do nothing at all :-(
321285
self.timeout = 120
@@ -337,7 +301,7 @@ def daemon_conf(self):
337301

338302
@property
339303
def logger(self):
340-
return self.server.configuration.daemon_conf['logger']
304+
return self.server.logger
341305

342306

343307
def limited_accept(logger, self, *args, **kwargs):
@@ -372,18 +336,16 @@ def start_service(configuration, host=None, port=None):
372336
assert host is not None, "required kwarg: host"
373337
assert port is not None, "required kwarg: port"
374338

375-
"""Service launcher"""
376-
daemon_conf = configuration.daemon_conf
377339
logger = configuration.logger
378340

379-
nossl = daemon_conf['nossl']
380-
addr = (host, port)
381341
# TODO: is this threaded version robust enough (thread safety)?
382342
# OpenIDServer = ApiHttpServer
383-
httpserver = ThreadedApiHttpServer(configuration, addr)
343+
def _on_start(server, *args, **kwargs):
344+
server.server_app = _create_and_expose_server(None, server.configuration)
345+
httpserver = ThreadedApiHttpServer(configuration, host=host, port=port, on_start=_on_start)
384346

385347
# Wrap in SSL if enabled
386-
if nossl:
348+
if True:
387349
logger.warning('Not wrapping connections in SSL - only for testing!')
388350
else:
389351
# Use best possible SSL/TLS args for this python version
@@ -415,152 +377,37 @@ def start_service(configuration, host=None, port=None):
415377
httpserver.expire_volatile()
416378

417379

418-
def _extend_configuration(configuration, address, port, **kwargs):
419-
configuration.daemon_conf = {
420-
'address': address,
421-
'port': port,
422-
'root_dir': os.path.abspath(configuration.user_home),
423-
'db_path': os.path.abspath(default_db_path(configuration)),
424-
'session_store': os.path.abspath(configuration.openid_store),
425-
'session_ttl': 24 * 3600,
426-
'allow_password': 'password' in configuration.user_openid_auth,
427-
'allow_digest': 'digest' in configuration.user_openid_auth,
428-
'allow_publickey': 'publickey' in configuration.user_openid_auth,
429-
'user_alias': configuration.user_openid_alias,
430-
'host_rsa_key': kwargs['host_rsa_key'],
431-
'users': [],
432-
'login_map': {},
433-
'time_stamp': 0,
434-
'logger': kwargs['logger'],
435-
'nossl': kwargs['nossl'],
436-
'expandusername': kwargs['expandusername'],
437-
'show_address': kwargs['show_address'],
438-
'show_port': kwargs['show_port'],
439-
'support_email': configuration.support_email,
440-
# TODO: Add the following to configuration:
441-
# max_openid_user_hits
442-
# max_openid_user_abuse_hits
443-
# max_openid_proto_abuse_hits
444-
# max_openid_secret_hits
445-
'auth_limits':
446-
{'max_user_hits': default_max_user_hits,
447-
'user_abuse_hits': default_user_abuse_hits,
448-
'proto_abuse_hits': default_proto_abuse_hits,
449-
'max_secret_hits': 1,
450-
},
451-
}
452-
453-
454-
def main():
455-
# Force no log init since we use separate logger
456-
configuration = get_configuration_object(skip_log=True)
380+
def main(configuration=None):
381+
if not configuration:
382+
# Force no log init since we use separate logger
383+
configuration = get_configuration_object(skip_log=True)
457384

458385
log_level = configuration.loglevel
459386
if sys.argv[1:] and sys.argv[1] in ['debug', 'info', 'warning', 'error']:
460387
log_level = sys.argv[1]
461388

462389
# Use separate logger
463-
logger = daemon_logger("openid", configuration.user_openid_log, log_level)
390+
logger = daemon_logger("coreapi", configuration.user_openid_log, log_level)
464391
configuration.logger = logger
465392

466393
# Allow e.g. logrotate to force log re-open after rotates
467394
register_hangup_handler(configuration)
468395

469-
# For masquerading
470-
show_address = configuration.user_openid_show_address
471-
show_port = configuration.user_openid_show_port
472-
473-
# Allow configuration overrides on command line
474-
nossl = False
475-
expandusername = False
476-
if sys.argv[2:]:
477-
configuration.user_openid_address = sys.argv[2]
478-
if sys.argv[3:]:
479-
configuration.user_openid_port = int(sys.argv[3])
480-
if sys.argv[4:]:
481-
nossl = (sys.argv[4].lower() in ('1', 'true', 'yes', 'on'))
482-
if sys.argv[5:]:
483-
expandusername = (sys.argv[5].lower() in ('1', 'true', 'yes', 'on'))
484-
485-
if not configuration.site_enable_openid:
486-
err_msg = "OpenID service is disabled in configuration!"
487-
logger.error(err_msg)
488-
print(err_msg)
489-
sys.exit(1)
490-
print("""
491-
Running grid openid server for user authentication against MiG user DB.
492-
493-
Set the MIG_CONF environment to the server configuration path
494-
unless it is available in mig/server/MiGserver.conf
495-
""")
496-
print(__doc__)
497-
498-
default_host_key = """
499-
-----BEGIN RSA PRIVATE KEY-----
500-
MIIEogIBAAKCAQEA404IBMReHOdvhhJ5YtgquY3DNi0v0QwfPUk+EcH/CxFW8UCC
501-
SUJe85up6lEQmOE9yKvrh+3yJgIjdV/ASOw9bd/u0NgNoPwl6A6P8GzHp94vz7UP
502-
nTp+PEUbA8gwqXnzzdeuF3dLDSXuGHdcv8qQEVRBwj/haecO0fgZcfd4fmLDAG53
503-
e/Vwc4lVIp4xx+OQowm9RW3nsAZge1DUoxlStD1/rEzBq1DvVx1Wu8pWS48f2ABH
504-
fHt2Z4ozypMB+a4B56jervcZCNkV/fN2bdGZ8z07hNbn/EkaH2tPw/d62zdHddum
505-
u7Pi0tYwMZz9GN3t18r9qi5ldUJuJNeNvNc7swIBIwKCAQBuZ7rAfKK9lPunhVDm
506-
3gYfnKClSSXakNv5MjQXQPg4k2S+UohsudZZERgEGL7rK5MJspb44Um6sJThPSLh
507-
l1EJe2VeH8wa/iEKUDdI5GD5w7DSmcXBZY3FgKa4sbE8X84wx9g3SJIq9SqA6YTS
508-
LzAIasDasVA6wK9tTJ6lEczPq2VkxkzpKauDMgI6SpaBV+7Un3OM7VJEbWeaJVoZ
509-
9I/2AHfp1hDpIfmaYBCnn2Ky70PBGA8DqAnHUKiid2dfZr8jKLu287LaUHxzIZXz
510-
qSzS6Vg1K0kc5FrgTgrjaXAGNtMenXZdw2/7PMuBDaNuNUApFUlAP5LGvPQ9IRCt
511-
YggDAoGBAP7z3lm74yxrzSa7HRASO2v3vp7jsbaYl4jPCc+6UruBFJlmUUdIQ2fh
512-
8i2S1M5mAvZiJ/PKLQ3r6RXxWZOeh4Vw479HFCVHr5GstSfLolJ5svY8iWEoEGdN
513-
D8aQTQrVAJwAPbLbF4eH5lgSokjOZcWMKsekk4vX2WmCMKWCMms/AoGBAOQ9Fffg
514-
B8TMc1b+jTcj1Py5TiFsxIe3usYjn8Pgg8kpoGfdBoS/TxwoR0MbJdrPgXDKLlLn
515-
A4GG6/7lFmxagCAfUyR2wAsOwAugcaFwS3K4QHGPiv9cgKxt9xhuhhDqXGI2lgAu
516-
oJLcRYBvomPQ+3cGGgifclETTWgkzD5dNVaNAoGBAMStf6RPHPZhyiUxQk4581NK
517-
FrUWDMAPUFOYZqePvCo/AUMjC4AhzZlH5rVxRRRAEOnz8u9EMWKCycB4Wwt6S0mu
518-
25OOmoMorAKpzZO6WKYGHFeNyRBvXRx9Rq8e3FjQM6uLKEglW0tLlG/T3EbLG09A
519-
PkI9IV1AHL8bShlHLjV5AoGBAJyBqKn4tN64FJNsuJrWve8f+w+bCmuxL53PSPtY
520-
H9plr9IxKQqRz9jLKY0Z7hJiZ2NIz07KS4wEvxUvX9VFXyv4OQMPmaEur5LxrQD8
521-
i4HdbgS6M21GvqIfhN2NncJ00aJukr5L29JrKFgSCPP9BDRb9Jgy0gu1duhTv0C0
522-
8V/rAoGAEUheXHIqv9n+3oXLvHadC3aApiz1TcyttDM0AjZoSHpXoBB3AIpPdU8O
523-
0drRG9zJTyU/BC02FvsGAMo0ZpGQRVMuN1Jj7sHsPaUdV38P4G0EaSQJDNxwFKVN
524-
3stfzMDGtKM9lntAsfFQ8n4yvvEbn/quEWad6srf1yxt9B4t5JA=
525-
-----END RSA PRIVATE KEY-----
526-
"""
396+
# FIXME:
397+
host = 'localhost' # configuration.user_openid_address
398+
port = 5555 # configuration.user_openid_port
399+
server_address = (host, port)
527400

528-
try:
529-
host_key_fd = open(configuration.user_openid_key, 'r')
530-
host_rsa_key = host_key_fd.read()
531-
host_key_fd.close()
532-
except IOError:
533-
logger.info("No valid host key provided - using default")
534-
host_rsa_key = default_host_key
535-
536-
address = configuration.user_openid_address
537-
port = configuration.user_openid_port
538-
_extend_configuration(
539-
configuration,
540-
address,
541-
port,
542-
logger=logger,
543-
expandusername=False,
544-
host_rsa_key=host_rsa_key,
545-
nossl=True,
546-
show_address=False,
547-
show_port=False,
548-
)
549-
550-
logger.info("Starting OpenID server")
551-
info_msg = "Listening on address '%s' and port %d" % (address, port)
401+
info_msg = "Starting coreapi..."
552402
logger.info(info_msg)
553403
print(info_msg)
404+
554405
try:
555-
start_service(configuration, host=address, port=port)
406+
start_service(configuration, host=host, port=port)
556407
except KeyboardInterrupt:
557408
info_msg = "Received user interrupt"
558409
logger.info(info_msg)
559410
print(info_msg)
560411
info_msg = "Leaving with no more workers active"
561412
logger.info(info_msg)
562413
print(info_msg)
563-
564-
565-
if __name__ == '__main__':
566-
main()

tests/test_mig_services_coreapi.py

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
testmain, temppath, make_wrapped_server
1212

1313
from mig.services.coreapi import ThreadedApiHttpServer, \
14-
_create_and_expose_server, _extend_configuration
14+
_create_and_expose_server
1515
from mig.shared.conf import get_configuration_object
1616

1717
_PYTHON_MAJOR = '2' if PY2 else '3'
@@ -106,9 +106,8 @@ def issue_POST(self, request_path, request_data=None, request_json=None):
106106
@unittest.skipIf(PY2, "Python 3 only")
107107
def test__GET_returns_not_found_for_missing_path(self):
108108
self.server_addr = ('localhost', 4567)
109-
configuration = self._make_configuration(self.logger, self.server_addr)
110-
self.server_thread = self._make_server(
111-
configuration).start_wait_until_ready()
109+
self.server_thread = self._make_server(self.configuration, self.logger, self.server_addr)
110+
self.server_thread.start_wait_until_ready()
112111

113112
status, _ = self.issue_request('/nonexistent')
114113

@@ -117,9 +116,8 @@ def test__GET_returns_not_found_for_missing_path(self):
117116
@unittest.skipIf(PY2, "Python 3 only")
118117
def test__GET_openid_user__top_level_request_succeeds_with_status_ok(self):
119118
self.server_addr = ('localhost', 4567)
120-
configuration = self._make_configuration(self.logger, self.server_addr)
121-
self.server_thread = self._make_server(
122-
configuration).start_wait_until_ready()
119+
self.server_thread = self._make_server(self.configuration, self.logger, self.server_addr)
120+
self.server_thread.start_wait_until_ready()
123121

124122
status, _ = self.issue_request('/user')
125123

@@ -136,12 +134,8 @@ def test_GET__openid_user_username__user_userid_request_succeeds_with_status_ok(
136134
test_user_db_home = os.path.join(test_state_dir, "user_db_home")
137135

138136
self.server_addr = ('localhost', 4567)
139-
configuration = self._make_configuration(self.logger, self.server_addr, overrides=dict(
140-
user_home=test_user_home,
141-
user_db_home=test_user_db_home,
142-
))
143-
self.server_thread = self._make_server(
144-
configuration).start_wait_until_ready()
137+
self.server_thread = self._make_server(self.configuration, self.logger, self.server_addr)
138+
self.server_thread.start_wait_until_ready()
145139

146140
the_url = '/user/%s' % (example_username,)
147141
status, body = self.issue_request(the_url)
@@ -154,9 +148,7 @@ def test_GET_openid_user_username(self):
154148
flask_app = None
155149

156150
self.server_addr = ('localhost', 4567)
157-
configuration = self._make_configuration(self.logger, self.server_addr)
158-
self.server_thread = self._make_server(configuration)
159-
# flask_app = _create_and_bind_flask_app_to_server(self.server_thread, configuration)
151+
self.server_thread = self._make_server(self.configuration, self.logger, self.server_addr)
160152
self.server_thread.start_wait_until_ready()
161153

162154
request_json = json.dumps({})
@@ -172,8 +164,7 @@ def test_POST_user__bad_input_data(self):
172164
flask_app = None
173165

174166
self.server_addr = ('localhost', 4567)
175-
configuration = self._make_configuration(self.logger, self.server_addr)
176-
self.server_thread = self._make_server(configuration)
167+
self.server_thread = self._make_server(self.configuration, self.logger, self.server_addr)
177168
self.server_thread.start_wait_until_ready()
178169

179170
status, content = self.issue_POST('/user', request_json={
@@ -187,8 +178,7 @@ def test_POST_user(self):
187178
flask_app = None
188179

189180
self.server_addr = ('localhost', 4567)
190-
configuration = self._make_configuration(self.logger, self.server_addr)
191-
self.server_thread = self._make_server(configuration)
181+
self.server_thread = self._make_server(self.configuration, self.logger, self.server_addr)
192182
self.server_thread.start_wait_until_ready()
193183

194184
status, content = self.issue_POST('/user', request_json={
@@ -214,12 +204,13 @@ def _make_configuration(self, test_logger, server_addr, overrides=None):
214204
return configuration
215205

216206
@staticmethod
217-
def _make_server(configuration):
207+
def _make_server(configuration, logger=None, server_address=None):
218208
def _on_instance(server):
219209
server.server_app = _create_and_expose_server(server.configuration)
220210

221-
server_thread = make_wrapped_server(
222-
ThreadedApiHttpServer, configuration, on_instance=_on_instance)
211+
(host, port) = server_address
212+
server_thread = make_wrapped_server(ThreadedApiHttpServer, \
213+
configuration, logger, host, port, on_instance=_on_instance)
223214
return server_thread
224215

225216

0 commit comments

Comments
 (0)