DevAuth support for reseller admins and an initial super admin. DevAuth server no longer needs the account ring or direct account server access. Proxy server supports account PUTs.
This commit is contained in:
parent
118ffba216
commit
b56bf3a0f3
@ -33,6 +33,16 @@ if __name__ == '__main__':
|
||||
default=False, help='Give the user administrator access; otherwise '
|
||||
'the user will only have access to containers specifically allowed '
|
||||
'with ACLs.')
|
||||
parser.add_option('-r', '--reseller-admin', dest='reseller_admin',
|
||||
action='store_true', default=False, help='Give the user full reseller '
|
||||
'administrator access, giving them full access to all accounts within '
|
||||
'the reseller, including the ability to create new accounts. Creating '
|
||||
'a new reseller admin requires super_admin rights.')
|
||||
parser.add_option('-U', '--admin-user', dest='admin_user',
|
||||
default='.super_admin', help='The user with admin rights to add users '
|
||||
'(default: .super_admin).')
|
||||
parser.add_option('-K', '--admin-key', dest='admin_key',
|
||||
help='The key for the user with admin rights to add users.')
|
||||
args = argv[1:]
|
||||
if not args:
|
||||
args.append('-h')
|
||||
@ -48,9 +58,13 @@ if __name__ == '__main__':
|
||||
port = int(conf.get('bind_port', 11000))
|
||||
ssl = conf.get('cert_file') is not None
|
||||
path = '/account/%s/%s' % (account, user)
|
||||
headers = {'X-Auth-User-Key': password}
|
||||
headers = {'X-Auth-Admin-User': options.admin_user,
|
||||
'X-Auth-Admin-Key': options.admin_key,
|
||||
'X-Auth-User-Key': password}
|
||||
if options.admin:
|
||||
headers['X-Auth-User-Admin'] = 'true'
|
||||
if options.reseller_admin:
|
||||
headers['X-Auth-User-Reseller-Admin'] = 'true'
|
||||
conn = http_connect(host, port, 'PUT', path, headers, ssl=ssl)
|
||||
resp = conn.getresponse()
|
||||
if resp.status == 204:
|
||||
|
@ -15,25 +15,37 @@
|
||||
# limitations under the License.
|
||||
|
||||
from ConfigParser import ConfigParser
|
||||
from optparse import OptionParser
|
||||
from sys import argv, exit
|
||||
|
||||
from swift.common.bufferedhttp import http_connect_raw as http_connect
|
||||
|
||||
if __name__ == '__main__':
|
||||
f = '/etc/swift/auth-server.conf'
|
||||
if len(argv) == 2:
|
||||
f = argv[1]
|
||||
elif len(argv) != 1:
|
||||
exit('Syntax: %s [conf_file]' % argv[0])
|
||||
default_conf = '/etc/swift/auth-server.conf'
|
||||
parser = OptionParser(usage='Usage: %prog [options]')
|
||||
parser.add_option('-c', '--conf', dest='conf', default=default_conf,
|
||||
help='Configuration file to determine how to connect to the local '
|
||||
'auth server (default: %s).' % default_conf)
|
||||
parser.add_option('-U', '--admin-user', dest='admin_user',
|
||||
default='.super_admin', help='The user with admin rights to recreate '
|
||||
'accounts (default: .super_admin).')
|
||||
parser.add_option('-K', '--admin-key', dest='admin_key',
|
||||
help='The key for the user with admin rights to recreate accounts.')
|
||||
args = argv[1:]
|
||||
if not args:
|
||||
args.append('-h')
|
||||
(options, args) = parser.parse_args(args)
|
||||
c = ConfigParser()
|
||||
if not c.read(f):
|
||||
exit('Unable to read conf file: %s' % f)
|
||||
if not c.read(options.conf):
|
||||
exit('Unable to read conf file: %s' % options.conf)
|
||||
conf = dict(c.items('app:auth-server'))
|
||||
host = conf.get('bind_ip', '127.0.0.1')
|
||||
port = int(conf.get('bind_port', 11000))
|
||||
ssl = conf.get('cert_file') is not None
|
||||
path = '/recreate_accounts'
|
||||
conn = http_connect(host, port, 'POST', path, ssl=ssl)
|
||||
conn = http_connect(host, port, 'POST', path, ssl=ssl,
|
||||
headers={'X-Auth-Admin-User': options.admin_user,
|
||||
'X-Auth-Admin-Key': options.admin_key})
|
||||
resp = conn.getresponse()
|
||||
if resp.status == 200:
|
||||
print resp.read()
|
||||
|
@ -177,6 +177,8 @@ good idea what to do on other environments.
|
||||
[app:auth-server]
|
||||
use = egg:swift#auth
|
||||
default_cluster_url = http://127.0.0.1:8080/v1
|
||||
# Highly recommended to change this.
|
||||
super_admin_key = devauth
|
||||
|
||||
#. Create `/etc/swift/proxy-server.conf`::
|
||||
|
||||
@ -511,7 +513,9 @@ good idea what to do on other environments.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
swift-auth-recreate-accounts
|
||||
# Replace devauth with whatever your super_admin key is (recorded in
|
||||
# /etc/swift/auth-server.conf).
|
||||
swift-auth-recreate-accounts -K devauth
|
||||
swift-init object-updater start
|
||||
swift-init container-updater start
|
||||
swift-init object-replicator start
|
||||
@ -526,12 +530,12 @@ good idea what to do on other environments.
|
||||
#. `remakerings`
|
||||
#. `cd ~/swift/trunk; ./.unittests`
|
||||
#. `startmain` (The ``Unable to increase file descriptor limit. Running as non-root?`` warnings are expected and ok.)
|
||||
#. `swift-auth-add-user --admin test tester testing`
|
||||
#. `swift-auth-add-user -K devauth -a test tester testing` # Replace ``devauth`` with whatever your super_admin key is (recorded in /etc/swift/auth-server.conf).
|
||||
#. Get an `X-Storage-Url` and `X-Auth-Token`: ``curl -v -H 'X-Storage-User: test:tester' -H 'X-Storage-Pass: testing' http://127.0.0.1:11000/v1.0``
|
||||
#. Check that you can GET account: ``curl -v -H 'X-Auth-Token: <token-from-x-auth-token-above>' <url-from-x-storage-url-above>``
|
||||
#. Check that `st` works: `st -A http://127.0.0.1:11000/v1.0 -U test:tester -K testing stat`
|
||||
#. `swift-auth-add-user --admin test2 tester2 testing2`
|
||||
#. `swift-auth-add-user test tester3 testing3`
|
||||
#. `swift-auth-add-user -K devauth -a test2 tester2 testing2` # Replace ``devauth`` with whatever your super_admin key is (recorded in /etc/swift/auth-server.conf).
|
||||
#. `swift-auth-add-user -K devauth test tester3 testing3` # Replace ``devauth`` with whatever your super_admin key is (recorded in /etc/swift/auth-server.conf).
|
||||
#. `cp ~/swift/trunk/test/functional/sample.conf /etc/swift/func_test.conf`
|
||||
#. `cd ~/swift/trunk; ./.functests` (Note: functional tests will first delete
|
||||
everything in the configured accounts.)
|
||||
|
@ -12,6 +12,8 @@ pipeline = auth-server
|
||||
|
||||
[app:auth-server]
|
||||
use = egg:swift#auth
|
||||
# Highly recommended to change this.
|
||||
super_admin_key = devauth
|
||||
# log_name = auth-server
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
|
@ -14,23 +14,21 @@
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import with_statement
|
||||
import errno
|
||||
import os
|
||||
import socket
|
||||
from contextlib import contextmanager
|
||||
from time import gmtime, strftime, time
|
||||
from urllib import unquote, quote
|
||||
from uuid import uuid4
|
||||
from urlparse import urlparse
|
||||
|
||||
import sqlite3
|
||||
from webob import Request, Response
|
||||
from webob.exc import HTTPBadRequest, HTTPNoContent, HTTPUnauthorized, \
|
||||
HTTPServiceUnavailable, HTTPNotFound
|
||||
from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPNoContent, \
|
||||
HTTPUnauthorized, HTTPServiceUnavailable, HTTPNotFound
|
||||
|
||||
from swift.common.bufferedhttp import http_connect
|
||||
from swift.common.bufferedhttp import http_connect_raw as http_connect
|
||||
from swift.common.db import get_db_connection
|
||||
from swift.common.ring import Ring
|
||||
from swift.common.utils import get_logger, normalize_timestamp, split_path
|
||||
from swift.common.utils import get_logger, split_path
|
||||
|
||||
|
||||
class AuthController(object):
|
||||
@ -69,8 +67,7 @@ class AuthController(object):
|
||||
|
||||
* The developer makes a ReST call to create a new user.
|
||||
* If the account for the user does not yet exist, the auth server makes
|
||||
ReST calls to the Swift cluster's account servers to create a new account
|
||||
on its end.
|
||||
a ReST call to the Swift cluster to create a new account on its end.
|
||||
* The auth server records the information in its database.
|
||||
|
||||
A last use case is recreating existing accounts; this is really only useful
|
||||
@ -78,34 +75,34 @@ class AuthController(object):
|
||||
the auth server's database is retained:
|
||||
|
||||
* A developer makes an ReST call to have the existing accounts recreated.
|
||||
* For each account in its database, the auth server makes ReST calls to
|
||||
the Swift cluster's account servers to create a specific account on its
|
||||
end.
|
||||
* For each account in its database, the auth server makes a ReST call to
|
||||
the Swift cluster to create the specific account on its end.
|
||||
|
||||
:param conf: The [auth-server] dictionary of the auth server configuration
|
||||
file
|
||||
:param ring: Overrides loading the account ring from a file; useful for
|
||||
testing.
|
||||
|
||||
See the etc/auth-server.conf-sample for information on the possible
|
||||
configuration parameters.
|
||||
"""
|
||||
|
||||
def __init__(self, conf, ring=None):
|
||||
def __init__(self, conf):
|
||||
self.logger = get_logger(conf)
|
||||
self.super_admin_key = conf.get('super_admin_key')
|
||||
if not self.super_admin_key:
|
||||
msg = 'No super_admin_key set in conf file! Exiting.'
|
||||
try:
|
||||
self.logger.critical(msg)
|
||||
except:
|
||||
pass
|
||||
raise ValueError(msg)
|
||||
self.swift_dir = conf.get('swift_dir', '/etc/swift')
|
||||
self.reseller_prefix = conf.get('reseller_prefix', 'AUTH').strip()
|
||||
if self.reseller_prefix and self.reseller_prefix[-1] != '_':
|
||||
self.reseller_prefix += '_'
|
||||
self.default_cluster_url = \
|
||||
conf.get('default_cluster_url', 'http://127.0.0.1:8080/v1')
|
||||
self.default_cluster_url = conf.get('default_cluster_url',
|
||||
'http://127.0.0.1:8080/v1').rstrip('/')
|
||||
self.token_life = int(conf.get('token_life', 86400))
|
||||
self.log_headers = conf.get('log_headers') == 'True'
|
||||
if ring:
|
||||
self.account_ring = ring
|
||||
else:
|
||||
self.account_ring = \
|
||||
Ring(os.path.join(self.swift_dir, 'account.ring.gz'))
|
||||
self.db_file = os.path.join(self.swift_dir, 'auth.db')
|
||||
self.conn = get_db_connection(self.db_file, okay_to_create=True)
|
||||
try:
|
||||
@ -114,9 +111,16 @@ class AuthController(object):
|
||||
if str(err) == 'no such column: admin':
|
||||
self.conn.execute("ALTER TABLE account ADD COLUMN admin TEXT")
|
||||
self.conn.execute("UPDATE account SET admin = 't'")
|
||||
try:
|
||||
self.conn.execute('SELECT reseller_admin FROM account LIMIT 1')
|
||||
except sqlite3.OperationalError, err:
|
||||
if str(err) == 'no such column: reseller_admin':
|
||||
self.conn.execute(
|
||||
"ALTER TABLE account ADD COLUMN reseller_admin TEXT")
|
||||
self.conn.execute('''CREATE TABLE IF NOT EXISTS account (
|
||||
account TEXT, url TEXT, cfaccount TEXT,
|
||||
user TEXT, password TEXT, admin TEXT)''')
|
||||
user TEXT, password TEXT, admin TEXT,
|
||||
reseller_admin TEXT)''')
|
||||
self.conn.execute('''CREATE INDEX IF NOT EXISTS ix_account_account
|
||||
ON account (account)''')
|
||||
try:
|
||||
@ -139,51 +143,36 @@ class AuthController(object):
|
||||
|
||||
def add_storage_account(self, account_name=''):
|
||||
"""
|
||||
Creates an account within the Swift cluster by making a ReST call to
|
||||
each of the responsible account servers.
|
||||
Creates an account within the Swift cluster by making a ReST call.
|
||||
|
||||
:param account_name: The desired name for the account; if omitted a
|
||||
UUID4 will be used.
|
||||
:returns: False upon failure, otherwise the name of the account
|
||||
within the Swift cluster.
|
||||
"""
|
||||
begin = time()
|
||||
orig_account_name = account_name
|
||||
if not account_name:
|
||||
account_name = '%s%s' % (self.reseller_prefix, uuid4().hex)
|
||||
partition, nodes = self.account_ring.get_nodes(account_name)
|
||||
headers = {'X-Timestamp': normalize_timestamp(time()),
|
||||
'x-cf-trans-id': 'tx' + str(uuid4())}
|
||||
statuses = []
|
||||
for node in nodes:
|
||||
try:
|
||||
conn = None
|
||||
conn = http_connect(node['ip'], node['port'], node['device'],
|
||||
partition, 'PUT', '/' + account_name, headers)
|
||||
source = conn.getresponse()
|
||||
statuses.append(source.status)
|
||||
if source.status >= 500:
|
||||
self.logger.error('ERROR With account server %s:%s/%s: '
|
||||
'Response %s %s: %s' %
|
||||
(node['ip'], node['port'], node['device'],
|
||||
source.status, source.reason, source.read(1024)))
|
||||
conn = None
|
||||
except BaseException, err:
|
||||
log_call = self.logger.exception
|
||||
msg = 'ERROR With account server ' \
|
||||
'%(ip)s:%(port)s/%(device)s (will retry later): ' % node
|
||||
if isinstance(err, socket.error):
|
||||
if err[0] == errno.ECONNREFUSED:
|
||||
log_call = self.logger.error
|
||||
msg += 'Connection refused'
|
||||
elif err[0] == errno.EHOSTUNREACH:
|
||||
log_call = self.logger.error
|
||||
msg += 'Host unreachable'
|
||||
log_call(msg)
|
||||
rv = False
|
||||
if len([s for s in statuses if (200 <= s < 300)]) > len(nodes) / 2:
|
||||
rv = account_name
|
||||
return rv
|
||||
url = '%s/%s' % (self.default_cluster_url, account_name)
|
||||
parsed = urlparse(url)
|
||||
# Create a single use token.
|
||||
token = '%stk%s' % (self.reseller_prefix, uuid4().hex)
|
||||
with self.get_conn() as conn:
|
||||
conn.execute('''
|
||||
INSERT INTO token
|
||||
(token, created, account, user, cfaccount) VALUES
|
||||
(?, ?, '.super_admin', '.single_use', '.reseller_admin')''',
|
||||
(token, time()))
|
||||
conn.commit()
|
||||
conn = http_connect(parsed.hostname, parsed.port, 'PUT', parsed.path,
|
||||
{'X-Auth-Token': token}, ssl=(parsed.scheme == 'https'))
|
||||
resp = conn.getresponse()
|
||||
resp.read()
|
||||
if resp.status // 100 != 2:
|
||||
self.logger.error('ERROR attempting to create account %s: %s %s' %
|
||||
(url, resp.status, resp.reason))
|
||||
return False
|
||||
return account_name
|
||||
|
||||
@contextmanager
|
||||
def get_conn(self):
|
||||
@ -229,7 +218,9 @@ class AuthController(object):
|
||||
|
||||
:param token: The token to validate
|
||||
:returns: (TTL, account, user, cfaccount) if valid, False otherwise.
|
||||
cfaccount will be None for users without admin access.
|
||||
cfaccount will be None for users without admin access for the
|
||||
account. cfaccount will be .reseller_admin for users with
|
||||
full reseller admin rights.
|
||||
"""
|
||||
begin = time()
|
||||
self.purge_old_tokens()
|
||||
@ -241,18 +232,20 @@ class AuthController(object):
|
||||
(token,)).fetchone()
|
||||
if row is not None:
|
||||
created = row[0]
|
||||
if time() - created >= self.token_life:
|
||||
if time() - created < self.token_life:
|
||||
rv = (self.token_life - (time() - created), row[1], row[2],
|
||||
row[3])
|
||||
# Remove the token if it was expired or single use.
|
||||
if not rv or rv[2] == '.single_use':
|
||||
conn.execute('''
|
||||
DELETE FROM token WHERE token = ?''', (token,))
|
||||
conn.commit()
|
||||
else:
|
||||
rv = (self.token_life - (time() - created), row[1], row[2],
|
||||
row[3])
|
||||
self.logger.info('validate_token(%s, _, _) = %s [%.02f]' %
|
||||
(repr(token), repr(rv), time() - begin))
|
||||
return rv
|
||||
|
||||
def create_user(self, account, user, password, admin=False):
|
||||
def create_user(self, account, user, password, admin=False,
|
||||
reseller_admin=False):
|
||||
"""
|
||||
Handles the create_user call for developers, used to request a user be
|
||||
added in the auth server database. If the account does not yet exist,
|
||||
@ -274,6 +267,9 @@ class AuthController(object):
|
||||
:param admin: If true, the user will be granted full access to the
|
||||
account; otherwise, another user will have to add the
|
||||
user to the ACLs for containers to grant access.
|
||||
:param reseller_admin: If true, the user will be granted full access to
|
||||
all accounts within this reseller, including the
|
||||
ability to create additional accounts.
|
||||
|
||||
:returns: False if the create fails, 'already exists' if the user
|
||||
already exists, or storage url if successful
|
||||
@ -287,9 +283,9 @@ class AuthController(object):
|
||||
(account, user)).fetchone()
|
||||
if row:
|
||||
self.logger.info(
|
||||
'ALREADY EXISTS create_user(%s, %s, _, %s) [%.02f]' %
|
||||
'ALREADY EXISTS create_user(%s, %s, _, %s, %s) [%.02f]' %
|
||||
(repr(account), repr(user), repr(admin),
|
||||
time() - begin))
|
||||
repr(reseller_admin), time() - begin))
|
||||
return 'already exists'
|
||||
row = conn.execute(
|
||||
'SELECT url, cfaccount FROM account WHERE account = ?',
|
||||
@ -301,21 +297,22 @@ class AuthController(object):
|
||||
account_hash = self.add_storage_account()
|
||||
if not account_hash:
|
||||
self.logger.info(
|
||||
'FAILED create_user(%s, %s, _, %s) [%.02f]' %
|
||||
'FAILED create_user(%s, %s, _, %s, %s) [%.02f]' %
|
||||
(repr(account), repr(user), repr(admin),
|
||||
time() - begin))
|
||||
repr(reseller_admin), time() - begin))
|
||||
return False
|
||||
url = self.default_cluster_url.rstrip('/') + '/' + account_hash
|
||||
conn.execute('''INSERT INTO account
|
||||
(account, url, cfaccount, user, password, admin)
|
||||
VALUES (?, ?, ?, ?, ?, ?)''',
|
||||
(account, url, cfaccount, user, password, admin,
|
||||
reseller_admin)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)''',
|
||||
(account, url, account_hash, user, password,
|
||||
admin and 't' or ''))
|
||||
admin and 't' or '', reseller_admin and 't' or ''))
|
||||
conn.commit()
|
||||
self.logger.info(
|
||||
'SUCCESS create_user(%s, %s, _, %s) = %s [%.02f]' %
|
||||
(repr(account), repr(user), repr(admin), repr(url),
|
||||
time() - begin))
|
||||
'SUCCESS create_user(%s, %s, _, %s, %s) = %s [%.02f]' %
|
||||
(repr(account), repr(user), repr(admin), repr(reseller_admin),
|
||||
repr(url), time() - begin))
|
||||
return url
|
||||
|
||||
def recreate_accounts(self):
|
||||
@ -339,6 +336,26 @@ class AuthController(object):
|
||||
(rv, time() - begin))
|
||||
return rv
|
||||
|
||||
def authorize_reseller_admin(self, request):
|
||||
if request.headers.get('X-Auth-Admin-User') == '.super_admin' and \
|
||||
request.headers.get('X-Auth-Admin-Key') == self.super_admin_key:
|
||||
return None
|
||||
try:
|
||||
account, user = \
|
||||
request.headers.get('X-Auth-Admin-User').split(':', 1)
|
||||
except ValueError:
|
||||
return HTTPForbidden(request=request)
|
||||
with self.get_conn() as conn:
|
||||
row = conn.execute('''
|
||||
SELECT user FROM account
|
||||
WHERE account = ? AND user = ? AND password = ? AND
|
||||
reseller_admin = 't' ''',
|
||||
(account, user,
|
||||
request.headers.get('X-Auth-Admin-Key'))).fetchone()
|
||||
if row:
|
||||
return None
|
||||
return HTTPForbidden(request=request)
|
||||
|
||||
def handle_token(self, request):
|
||||
"""
|
||||
Handles ReST requests from Swift to validate tokens
|
||||
@ -362,7 +379,9 @@ class AuthController(object):
|
||||
if not validation:
|
||||
return HTTPNotFound()
|
||||
groups = ['%s:%s' % (validation[1], validation[2]), validation[1]]
|
||||
if validation[3]: # admin access to a cfaccount
|
||||
if validation[3]:
|
||||
# admin access to a cfaccount or ".reseller_admin" to access to all
|
||||
# accounts, including creating new ones.
|
||||
groups.append(validation[3])
|
||||
return HTTPNoContent(headers={'X-Auth-TTL': validation[0],
|
||||
'X-Auth-Groups': ','.join(groups)})
|
||||
@ -380,6 +399,7 @@ class AuthController(object):
|
||||
Valid headers:
|
||||
* X-Auth-User-Key: <password>
|
||||
* X-Auth-User-Admin: <true|false>
|
||||
* X-Auth-User-Reseller-Admin: <true|false>
|
||||
|
||||
If the HTTP request returns with a 204, then the user was added,
|
||||
and the storage url will be available in the X-Storage-Url header.
|
||||
@ -390,11 +410,21 @@ class AuthController(object):
|
||||
_, account_name, user_name = split_path(request.path, minsegs=3)
|
||||
except ValueError:
|
||||
return HTTPBadRequest()
|
||||
create_reseller_admin = \
|
||||
request.headers.get('x-auth-user-reseller-admin') == 'true'
|
||||
if create_reseller_admin and (
|
||||
request.headers.get('X-Auth-Admin-User') != '.super_admin' or
|
||||
request.headers.get('X-Auth-Admin-Key') != self.super_admin_key):
|
||||
return HTTPForbidden(request=request)
|
||||
resp = self.authorize_reseller_admin(request)
|
||||
if resp:
|
||||
return resp
|
||||
if 'X-Auth-User-Key' not in request.headers:
|
||||
return HTTPBadRequest('X-Auth-User-Key is required')
|
||||
password = request.headers['x-auth-user-key']
|
||||
storage_url = self.create_user(account_name, user_name, password,
|
||||
request.headers.get('x-auth-user-admin') == 'true')
|
||||
request.headers.get('x-auth-user-admin') == 'true',
|
||||
create_reseller_admin)
|
||||
if storage_url == 'already exists':
|
||||
return HTTPBadRequest(storage_url)
|
||||
if not storage_url:
|
||||
@ -412,6 +442,9 @@ class AuthController(object):
|
||||
|
||||
:param request: webob.Request object
|
||||
"""
|
||||
if request.headers.get('X-Auth-Admin-User') != '.super_admin' or \
|
||||
request.headers.get('X-Auth-Admin-Key') != self.super_admin_key:
|
||||
return HTTPForbidden(request=request)
|
||||
result = self.recreate_accounts()
|
||||
return Response(result, 200, request=request)
|
||||
|
||||
@ -471,7 +504,7 @@ class AuthController(object):
|
||||
self.purge_old_tokens()
|
||||
with self.get_conn() as conn:
|
||||
row = conn.execute('''
|
||||
SELECT cfaccount, url, admin FROM account
|
||||
SELECT cfaccount, url, admin, reseller_admin FROM account
|
||||
WHERE account = ? AND user = ? AND password = ?''',
|
||||
(account, user, password)).fetchone()
|
||||
if row is None:
|
||||
@ -479,6 +512,7 @@ class AuthController(object):
|
||||
cfaccount = row[0]
|
||||
url = row[1]
|
||||
admin = row[2] == 't'
|
||||
reseller_admin = row[3] == 't'
|
||||
row = conn.execute('''
|
||||
SELECT token FROM token WHERE account = ? AND user = ?''',
|
||||
(account, user)).fetchone()
|
||||
@ -486,11 +520,16 @@ class AuthController(object):
|
||||
token = row[0]
|
||||
else:
|
||||
token = '%stk%s' % (self.reseller_prefix, uuid4().hex)
|
||||
token_cfaccount = ''
|
||||
if admin:
|
||||
token_cfaccount = cfaccount
|
||||
if reseller_admin:
|
||||
token_cfaccount = '.reseller_admin'
|
||||
conn.execute('''
|
||||
INSERT INTO token
|
||||
(token, created, account, user, cfaccount)
|
||||
VALUES (?, ?, ?, ?, ?)''',
|
||||
(token, time(), account, user, admin and cfaccount or ''))
|
||||
(token, time(), account, user, token_cfaccount))
|
||||
conn.commit()
|
||||
return HTTPNoContent(headers={'x-auth-token': token,
|
||||
'x-storage-token': token,
|
||||
|
@ -36,6 +36,8 @@ MAX_OBJECT_NAME_LENGTH = 1024
|
||||
CONTAINER_LISTING_LIMIT = 10000
|
||||
#: Max container list length of a get request for an account
|
||||
ACCOUNT_LISTING_LIMIT = 10000
|
||||
MAX_ACCOUNT_NAME_LENGTH = 256
|
||||
MAX_CONTAINER_NAME_LENGTH = 256
|
||||
|
||||
|
||||
def check_metadata(req, target_type):
|
||||
|
@ -49,7 +49,7 @@ class DevAuth(object):
|
||||
token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
|
||||
if token and token.startswith(self.reseller_prefix):
|
||||
memcache_client = cache_from_env(env)
|
||||
key = 'devauth/%s' % token
|
||||
key = '%s/token/%s' % (self.reseller_prefix, token)
|
||||
cached_auth_data = memcache_client.get(key)
|
||||
if cached_auth_data:
|
||||
start, expiration, groups = cached_auth_data
|
||||
@ -85,14 +85,19 @@ class DevAuth(object):
|
||||
version, account, container, obj = split_path(req.path, 1, 4, True)
|
||||
if not account or not account.startswith(self.reseller_prefix):
|
||||
return self.denied_response(req)
|
||||
if req.remote_user and account in req.remote_user.split(','):
|
||||
user_groups = (req.remote_user or '').split(',')
|
||||
if '.reseller_admin' in user_groups:
|
||||
return None
|
||||
if account in user_groups and (req.method != 'PUT' or container):
|
||||
# If the user is admin for the account and is not trying to do an
|
||||
# account PUT...
|
||||
return None
|
||||
referrers, groups = parse_acl(getattr(req, 'acl', None))
|
||||
if referrer_allowed(req.referer, referrers):
|
||||
return None
|
||||
if not req.remote_user:
|
||||
return self.denied_response(req)
|
||||
for user_group in req.remote_user.split(','):
|
||||
for user_group in user_groups:
|
||||
if user_group in groups:
|
||||
return None
|
||||
return self.denied_response(req)
|
||||
|
@ -35,13 +35,12 @@ from swift.common.ring import Ring
|
||||
from swift.common.utils import get_logger, normalize_timestamp, split_path, \
|
||||
cache_from_env
|
||||
from swift.common.bufferedhttp import http_connect
|
||||
from swift.common.constraints import check_object_creation, check_metadata, \
|
||||
MAX_FILE_SIZE, check_xml_encodable
|
||||
from swift.common.constraints import check_metadata, check_object_creation, \
|
||||
check_xml_encodable, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH, \
|
||||
MAX_FILE_SIZE
|
||||
from swift.common.exceptions import ChunkReadTimeout, \
|
||||
ChunkWriteTimeout, ConnectionTimeout
|
||||
|
||||
MAX_CONTAINER_NAME_LENGTH = 256
|
||||
|
||||
|
||||
def update_headers(response, headers):
|
||||
"""
|
||||
@ -1079,6 +1078,59 @@ class AccountController(Controller):
|
||||
return self.GETorHEAD_base(req, 'Account', partition, nodes,
|
||||
req.path_info.rstrip('/'), self.app.account_ring.replica_count)
|
||||
|
||||
@public
|
||||
def PUT(self, req):
|
||||
"""HTTP PUT request handler."""
|
||||
error_response = check_metadata(req, 'account')
|
||||
if error_response:
|
||||
return error_response
|
||||
if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
|
||||
resp = HTTPBadRequest(request=req)
|
||||
resp.body = 'Account name length of %d longer than %d' % \
|
||||
(len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)
|
||||
return resp
|
||||
account_partition, accounts = \
|
||||
self.app.account_ring.get_nodes(self.account_name)
|
||||
headers = {'X-Timestamp': normalize_timestamp(time.time()),
|
||||
'x-cf-trans-id': self.trans_id}
|
||||
headers.update(value for value in req.headers.iteritems()
|
||||
if value[0].lower().startswith('x-account-meta-'))
|
||||
statuses = []
|
||||
reasons = []
|
||||
bodies = []
|
||||
for node in self.iter_nodes(account_partition, accounts,
|
||||
self.app.account_ring):
|
||||
if self.error_limited(node):
|
||||
continue
|
||||
try:
|
||||
with ConnectionTimeout(self.app.conn_timeout):
|
||||
conn = http_connect(node['ip'], node['port'],
|
||||
node['device'], account_partition, 'PUT',
|
||||
req.path_info, headers)
|
||||
with Timeout(self.app.node_timeout):
|
||||
source = conn.getresponse()
|
||||
body = source.read()
|
||||
if 200 <= source.status < 300 \
|
||||
or 400 <= source.status < 500:
|
||||
statuses.append(source.status)
|
||||
reasons.append(source.reason)
|
||||
bodies.append(body)
|
||||
else:
|
||||
if source.status == 507:
|
||||
self.error_limit(node)
|
||||
except:
|
||||
self.exception_occurred(node, 'Account',
|
||||
'Trying to PUT to %s' % req.path)
|
||||
if len(statuses) >= len(accounts):
|
||||
break
|
||||
while len(statuses) < len(accounts):
|
||||
statuses.append(503)
|
||||
reasons.append('')
|
||||
bodies.append('')
|
||||
self.app.memcache.delete('account%s' % req.path_info.rstrip('/'))
|
||||
return self.best_response(req, statuses, reasons, bodies,
|
||||
'Account PUT')
|
||||
|
||||
@public
|
||||
def POST(self, req):
|
||||
"""HTTP POST request handler."""
|
||||
|
@ -124,7 +124,7 @@ class Connection(object):
|
||||
if response.status == 401:
|
||||
raise AuthenticationFailed()
|
||||
|
||||
if response.status != 204:
|
||||
if response.status not in (200, 204):
|
||||
raise ResponseError(response)
|
||||
|
||||
for hdr in response.getheaders():
|
||||
|
@ -172,7 +172,7 @@ class TestAccount(Base):
|
||||
|
||||
def testPUT(self):
|
||||
self.env.account.conn.make_request('PUT')
|
||||
self.assert_status(405)
|
||||
self.assert_status([403, 405])
|
||||
|
||||
def testAccountHead(self):
|
||||
try_count = 0
|
||||
|
@ -63,12 +63,6 @@ def fake_http_connect(*code_iter, **kwargs):
|
||||
return connect
|
||||
|
||||
|
||||
class FakeRing(object):
|
||||
def get_nodes(self, path):
|
||||
return 1, [{'ip': '10.0.0.%s' % x, 'port': 1000+x, 'device': 'sda'}
|
||||
for x in xrange(3)]
|
||||
|
||||
|
||||
class TestAuthServer(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -76,8 +70,9 @@ class TestAuthServer(unittest.TestCase):
|
||||
'auth_server')
|
||||
rmtree(self.testdir, ignore_errors=1)
|
||||
os.mkdir(self.testdir)
|
||||
self.conf = {'swift_dir': self.testdir, 'log_name': 'auth'}
|
||||
self.controller = auth_server.AuthController(self.conf, FakeRing())
|
||||
self.conf = {'swift_dir': self.testdir, 'log_name': 'auth',
|
||||
'super_admin_key': 'testkey'}
|
||||
self.controller = auth_server.AuthController(self.conf)
|
||||
|
||||
def tearDown(self):
|
||||
rmtree(self.testdir, ignore_errors=1)
|
||||
@ -106,7 +101,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assert_(conn is not None)
|
||||
|
||||
def test_validate_token_non_existant_token(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing',).split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -117,7 +112,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(self.controller.validate_token(token + 'bad'), False)
|
||||
|
||||
def test_validate_token_good(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing',).split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -132,7 +127,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
orig_time = auth_server.time
|
||||
try:
|
||||
auth_server.time = lambda: 1
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user('test', 'tester',
|
||||
'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -148,107 +143,98 @@ class TestAuthServer(unittest.TestCase):
|
||||
auth_server.time = orig_time
|
||||
|
||||
def test_create_user_no_new_account(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
result = self.controller.create_user('', 'tester', 'testing')
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_create_user_no_new_user(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
result = self.controller.create_user('test', '', 'testing')
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_create_user_no_new_password(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
result = self.controller.create_user('test', 'tester', '')
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_create_user_good(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test', 'tester', 'testing')
|
||||
self.assert_(url)
|
||||
self.assertEquals('/'.join(url.split('/')[:-1]),
|
||||
self.controller.default_cluster_url.rstrip('/'), repr(url))
|
||||
|
||||
def test_recreate_accounts_none(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
rv = self.controller.recreate_accounts()
|
||||
self.assertEquals(rv.split()[0], '0', repr(rv))
|
||||
self.assertEquals(rv.split()[-1], '[]', repr(rv))
|
||||
|
||||
def test_recreate_accounts_one(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.controller.create_user('test', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
rv = self.controller.recreate_accounts()
|
||||
self.assertEquals(rv.split()[0], '1', repr(rv))
|
||||
self.assertEquals(rv.split()[-1], '[]', repr(rv))
|
||||
|
||||
def test_recreate_accounts_several(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.controller.create_user('test1', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.controller.create_user('test2', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.controller.create_user('test3', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.controller.create_user('test4', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201,
|
||||
201, 201, 201,
|
||||
201, 201, 201,
|
||||
201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201, 201)
|
||||
rv = self.controller.recreate_accounts()
|
||||
self.assertEquals(rv.split()[0], '4', repr(rv))
|
||||
self.assertEquals(rv.split()[-1], '[]', repr(rv))
|
||||
|
||||
def test_recreate_accounts_one_fail(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test', 'tester', 'testing')
|
||||
cfaccount = url.split('/')[-1]
|
||||
auth_server.http_connect = fake_http_connect(500, 500, 500)
|
||||
auth_server.http_connect = fake_http_connect(500)
|
||||
rv = self.controller.recreate_accounts()
|
||||
self.assertEquals(rv.split()[0], '1', repr(rv))
|
||||
self.assertEquals(rv.split()[-1], '[%s]' % repr(cfaccount),
|
||||
repr(rv))
|
||||
|
||||
def test_recreate_accounts_several_fail(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test1', 'tester', 'testing')
|
||||
cfaccounts = [url.split('/')[-1]]
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test2', 'tester', 'testing')
|
||||
cfaccounts.append(url.split('/')[-1])
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test3', 'tester', 'testing')
|
||||
cfaccounts.append(url.split('/')[-1])
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test4', 'tester', 'testing')
|
||||
cfaccounts.append(url.split('/')[-1])
|
||||
auth_server.http_connect = fake_http_connect(500, 500, 500,
|
||||
500, 500, 500,
|
||||
500, 500, 500,
|
||||
500, 500, 500)
|
||||
auth_server.http_connect = fake_http_connect(500, 500, 500, 500)
|
||||
rv = self.controller.recreate_accounts()
|
||||
self.assertEquals(rv.split()[0], '4', repr(rv))
|
||||
failed = rv.split('[', 1)[-1][:-1].split(', ')
|
||||
self.assertEquals(set(failed), set(repr(a) for a in cfaccounts))
|
||||
|
||||
def test_recreate_accounts_several_fail_some(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test1', 'tester', 'testing')
|
||||
cfaccounts = [url.split('/')[-1]]
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test2', 'tester', 'testing')
|
||||
cfaccounts.append(url.split('/')[-1])
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test3', 'tester', 'testing')
|
||||
cfaccounts.append(url.split('/')[-1])
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test4', 'tester', 'testing')
|
||||
cfaccounts.append(url.split('/')[-1])
|
||||
auth_server.http_connect = fake_http_connect(500, 500, 500,
|
||||
201, 201, 201,
|
||||
500, 500, 500,
|
||||
201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(500, 201, 500, 201)
|
||||
rv = self.controller.recreate_accounts()
|
||||
self.assertEquals(rv.split()[0], '4', repr(rv))
|
||||
failed = rv.split('[', 1)[-1][:-1].split(', ')
|
||||
@ -263,7 +249,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 400)
|
||||
|
||||
def test_auth_SOSO_missing_headers(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -279,7 +265,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_SOSO_bad_account(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/testbad/auth',
|
||||
@ -294,7 +280,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_SOSO_bad_user(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -309,7 +295,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_SOSO_bad_password(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -324,7 +310,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_SOSO_good(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -336,7 +322,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assert_(ttl > 0, repr(ttl))
|
||||
|
||||
def test_auth_SOSO_good_Mosso_headers(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -348,7 +334,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assert_(ttl > 0, repr(ttl))
|
||||
|
||||
def test_auth_SOSO_bad_Mosso_headers(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing',).split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/v1/test/auth',
|
||||
@ -368,7 +354,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_Mosso_missing_headers(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -384,7 +370,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_Mosso_bad_header_format(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -399,7 +385,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_Mosso_bad_account(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -414,7 +400,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_Mosso_bad_user(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -429,7 +415,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_Mosso_bad_password(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -444,7 +430,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assertEquals(res.status_int, 401)
|
||||
|
||||
def test_auth_Mosso_good(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -456,7 +442,7 @@ class TestAuthServer(unittest.TestCase):
|
||||
self.assert_(ttl > 0, repr(ttl))
|
||||
|
||||
def test_auth_Mosso_good_SOSO_header_names(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
cfaccount = self.controller.create_user(
|
||||
'test', 'tester', 'testing').split('/')[-1]
|
||||
res = self.controller.handle_auth(Request.blank('/auth',
|
||||
@ -473,11 +459,11 @@ class TestAuthServer(unittest.TestCase):
|
||||
logger = get_logger(self.conf, 'auth')
|
||||
logger.logger.addHandler(log_handler)
|
||||
try:
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test', 'tester', 'testing')
|
||||
self.assertEquals(log.getvalue().rsplit(' ', 1)[0],
|
||||
"auth SUCCESS create_user('test', 'tester', _, False) = %s"
|
||||
% repr(url))
|
||||
"auth SUCCESS create_user('test', 'tester', _, False, False) "
|
||||
"= %s" % repr(url))
|
||||
log.truncate(0)
|
||||
def start_response(*args):
|
||||
pass
|
||||
@ -603,8 +589,8 @@ class TestAuthServer(unittest.TestCase):
|
||||
conn.commit()
|
||||
conn.close()
|
||||
# Upgrade to current db
|
||||
conf = {'swift_dir': swift_dir}
|
||||
controller = auth_server.AuthController(conf, FakeRing())
|
||||
conf = {'swift_dir': swift_dir, 'super_admin_key': 'testkey'}
|
||||
controller = auth_server.AuthController(conf)
|
||||
# Check new items exist and are correct
|
||||
conn = get_db_connection(db_file)
|
||||
row = conn.execute('SELECT admin FROM account').fetchone()
|
||||
@ -615,17 +601,17 @@ class TestAuthServer(unittest.TestCase):
|
||||
rmtree(swift_dir)
|
||||
|
||||
def test_create_user_twice(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.controller.create_user('test', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
self.assertEquals(
|
||||
self.controller.create_user('test', 'tester', 'testing'),
|
||||
'already exists')
|
||||
|
||||
def test_create_2users_1account(self):
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url = self.controller.create_user('test', 'tester', 'testing')
|
||||
auth_server.http_connect = fake_http_connect(201, 201, 201)
|
||||
auth_server.http_connect = fake_http_connect(201)
|
||||
url2 = self.controller.create_user('test', 'tester2', 'testing2')
|
||||
self.assertEquals(url, url2)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user