26 |
26 |
import optparse
|
27 |
27 |
import sys
|
28 |
28 |
import os
|
|
29 |
import os.path
|
29 |
30 |
import signal
|
30 |
31 |
|
31 |
32 |
from ganeti import constants
|
... | ... | |
36 |
37 |
from ganeti import utils
|
37 |
38 |
from ganeti.rapi import connector
|
38 |
39 |
|
|
40 |
import ganeti.http.auth
|
39 |
41 |
import ganeti.http.server
|
40 |
42 |
|
41 |
43 |
|
... | ... | |
46 |
48 |
def __init__(self):
|
47 |
49 |
self.handler = None
|
48 |
50 |
self.handler_fn = None
|
|
51 |
self.handler_access = None
|
49 |
52 |
|
50 |
53 |
|
51 |
|
class RemoteApiHttpServer(http.server.HttpServer):
|
|
54 |
class RemoteApiHttpServer(http.auth.HttpServerRequestAuthentication,
|
|
55 |
http.server.HttpServer):
|
52 |
56 |
"""REST Request Handler Class.
|
53 |
57 |
|
54 |
58 |
"""
|
|
59 |
AUTH_REALM = "Ganeti Remote API"
|
|
60 |
|
55 |
61 |
def __init__(self, *args, **kwargs):
|
56 |
62 |
http.server.HttpServer.__init__(self, *args, **kwargs)
|
|
63 |
http.auth.HttpServerRequestAuthentication.__init__(self)
|
57 |
64 |
self._resmap = connector.Mapper()
|
58 |
65 |
|
|
66 |
# Load password file
|
|
67 |
if os.path.isfile(constants.RAPI_USERS_FILE):
|
|
68 |
self._users = http.auth.ReadPasswordFile(constants.RAPI_USERS_FILE)
|
|
69 |
else:
|
|
70 |
self._users = None
|
|
71 |
|
59 |
72 |
def _GetRequestContext(self, req):
|
60 |
73 |
"""Returns the context for a request.
|
61 |
74 |
|
... | ... | |
74 |
87 |
except AttributeError, err:
|
75 |
88 |
raise http.HttpBadRequest()
|
76 |
89 |
|
|
90 |
ctx.handler_access = getattr(ctx.handler, "%s_ACCESS" % method, None)
|
|
91 |
|
|
92 |
# Require permissions definition (usually in the base class)
|
|
93 |
if ctx.handler_access is None:
|
|
94 |
raise AssertionError("Permissions definition missing")
|
|
95 |
|
77 |
96 |
req.private = ctx
|
78 |
97 |
|
79 |
98 |
return req.private
|
80 |
99 |
|
|
100 |
def Authenticate(self, req, username, password):
|
|
101 |
"""Checks whether a user can access a resource.
|
|
102 |
|
|
103 |
"""
|
|
104 |
ctx = self._GetRequestContext(req)
|
|
105 |
|
|
106 |
# Check username and password
|
|
107 |
valid_user = False
|
|
108 |
if self._users:
|
|
109 |
user = self._users.get(username, None)
|
|
110 |
if user and user.password == password:
|
|
111 |
valid_user = True
|
|
112 |
|
|
113 |
if not valid_user:
|
|
114 |
# Unknown user or password wrong
|
|
115 |
return False
|
|
116 |
|
|
117 |
if (not ctx.handler_access or
|
|
118 |
set(user.options).intersection(ctx.handler_access)):
|
|
119 |
# Allow access
|
|
120 |
return True
|
|
121 |
|
|
122 |
# Access forbidden
|
|
123 |
raise http.HttpForbidden()
|
|
124 |
|
81 |
125 |
def HandleRequest(self, req):
|
82 |
126 |
"""Handles a request.
|
83 |
127 |
|