Revision b5b67ef9 daemons/ganeti-rapi
b/daemons/ganeti-rapi | ||
---|---|---|
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 |
|
Also available in: Unified diff