1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 """Ganeti Remote API master script.
31
32 """
33
34
35
36
37
38 import logging
39 import optparse
40 import sys
41
42 from ganeti import constants
43 from ganeti import http
44 from ganeti import daemon
45 from ganeti import ssconf
46 import ganeti.rpc.errors as rpcerr
47 from ganeti import serializer
48 from ganeti import pathutils
49 from ganeti.rapi import connector
50 from ganeti.rapi import baserlib
51 from ganeti.rapi.auth import basic_auth
52 from ganeti.rapi.auth import pam
53
54 import ganeti.http.auth
55 import ganeti.http.server
56
57
58 -class RemoteApiRequestContext(object):
59 """Data structure for Remote API requests.
60
61 """
63 self.handler = None
64 self.handler_fn = None
65 self.handler_access = None
66 self.body_data = None
67
68
69 -class RemoteApiHandler(http.auth.HttpServerRequestAuthentication,
70 http.server.HttpServerHandler):
71 """REST Request Handler Class.
72
73 """
74 AUTH_REALM = "Ganeti Remote API"
75
76 - def __init__(self, authenticator, reqauth, _client_cls=None):
77 """Initializes this class.
78
79 @type authenticator: an implementation of {RapiAuthenticator} interface
80 @param authenticator: a class containing an implementation of
81 ValidateRequest function
82 @type reqauth: bool
83 @param reqauth: Whether to require authentication
84
85 """
86
87
88 http.server.HttpServerHandler.__init__(self)
89 http.auth.HttpServerRequestAuthentication.__init__(self)
90 self._client_cls = _client_cls
91 self._resmap = connector.Mapper()
92 self._authenticator = authenticator
93 self._reqauth = reqauth
94
95 @staticmethod
106
107 - def _GetRequestContext(self, req):
108 """Returns the context for a request.
109
110 The context is cached in the req.private variable.
111
112 """
113 if req.private is None:
114 (HandlerClass, items, args) = \
115 self._resmap.getController(req.request_path)
116
117 ctx = RemoteApiRequestContext()
118 ctx.handler = HandlerClass(items, args, req, _client_cls=self._client_cls)
119
120 method = req.request_method.upper()
121 try:
122 ctx.handler_fn = getattr(ctx.handler, method)
123 except AttributeError:
124 raise http.HttpNotImplemented("Method %s is unsupported for path %s" %
125 (method, req.request_path))
126
127 ctx.handler_access = baserlib.GetHandlerAccess(ctx.handler, method)
128
129
130 if ctx.handler_access is None:
131 raise AssertionError("Permissions definition missing")
132
133
134 ctx.body_data = None
135
136 req.private = ctx
137
138
139 assert req.private.handler
140 assert req.private.handler_fn
141 assert req.private.handler_access is not None
142
143 return req.private
144
146 """Determine whether authentication is required.
147
148 """
149 return self._reqauth
150
152 """Checks whether a user can access a resource.
153
154 @return: username of an authenticated user or None otherwise
155 """
156 ctx = self._GetRequestContext(req)
157 auth_user = self._authenticator.ValidateRequest(
158 req, ctx.handler_access, self.GetAuthRealm(req))
159 if auth_user is None:
160 return False
161
162 ctx.handler.auth_user = auth_user
163 return True
164
199
218
241
242
243 -def ExecRapi(options, args, prep_data):
244 """Main remote API function, executed with the PID file held.
245
246 """
247
248 (mainloop, server) = prep_data
249 try:
250 mainloop.Run()
251 finally:
252 logging.error("RAPI Daemon Failed")
253 server.Stop()
254
257 """Main function.
258
259 """
260 parser = optparse.OptionParser(description="Ganeti Remote API",
261 usage=("%prog [-f] [-d] [-p port] [-b ADDRESS]"
262 " [-i INTERFACE]"),
263 version="%%prog (ganeti) %s" %
264 constants.RELEASE_VERSION)
265 parser.add_option("--require-authentication", dest="reqauth",
266 default=False, action="store_true",
267 help=("Disable anonymous HTTP requests and require"
268 " authentication"))
269 parser.add_option("--pam-authentication", dest="pamauth",
270 default=False, action="store_true",
271 help=("Enable RAPI authentication and authorization via"
272 " PAM"))
273
274 daemon.GenericMain(constants.RAPI, parser, CheckRapi, PrepRapi, ExecRapi,
275 default_ssl_cert=pathutils.RAPI_CERT_FILE,
276 default_ssl_key=pathutils.RAPI_CERT_FILE)
277