Revision b5b67ef9

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

  
b/lib/constants.py
96 96
SSL_CERT_FILE = DATA_DIR + "/server.pem"
97 97
WATCHER_STATEFILE = DATA_DIR + "/watcher.data"
98 98
SSH_KNOWN_HOSTS_FILE = DATA_DIR + "/known_hosts"
99
RAPI_USERS_FILE = DATA_DIR + "/rapi_users"
99 100
QUEUE_DIR = DATA_DIR + "/queue"
100 101
ETC_HOSTS = "/etc/hosts"
101 102
DEFAULT_FILE_STORAGE_DIR = _autoconf.FILE_STORAGE_DIR
b/lib/rapi/__init__.py
19 19
# 02110-1301, USA.
20 20

  
21 21

  
22
# empty file for package definition
22
RAPI_ACCESS_WRITE = "write"
b/lib/rapi/baserlib.py
27 27
import ganeti.opcodes
28 28

  
29 29
from ganeti import luxi
30
from ganeti import rapi
30 31

  
31 32

  
32 33
def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
......
149 150
  """Generic class for resources.
150 151

  
151 152
  """
153
  # Default permission requirements
154
  GET_ACCESS = []
155
  PUT_ACCESS = [rapi.RAPI_ACCESS_WRITE]
156
  POST_ACCESS = [rapi.RAPI_ACCESS_WRITE]
157
  DELETE_ACCESS = [rapi.RAPI_ACCESS_WRITE]
158

  
152 159
  def __init__(self, items, queryargs, req):
153 160
    """Generic resource constructor.
154 161

  

Also available in: Unified diff