summaryrefslogtreecommitdiffstats
path: root/testapi
diff options
context:
space:
mode:
authorSerenaFeng <feng.xiaowei@zte.com.cn>2017-08-30 11:59:46 +0800
committerSerenaFeng <feng.xiaowei@zte.com.cn>2017-08-31 10:43:14 +0800
commit9e36409f1bf52a6fd510c4f4896d85761b59cfa9 (patch)
treeb5917ad3530efb2856a9a398a78cb7fca3af9e2e /testapi
parentea7706279a99c03181c348d29c157f70037ed217 (diff)
leverage LFID as Authentication
delete openid authentication add LFID authentication Change-Id: Iead144b5130bce51448024e65092fdea3bb2f07a Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
Diffstat (limited to 'testapi')
-rw-r--r--testapi/.gitignore2
-rw-r--r--testapi/3rd_party/static/testapi-ui/components/profile/profile.html11
-rw-r--r--testapi/3rd_party/static/testapi-ui/components/profile/profileController.js2
-rw-r--r--testapi/etc/config.ini48
-rw-r--r--testapi/opnfv_testapi/common/check.py35
-rw-r--r--testapi/opnfv_testapi/common/constants.py5
-rw-r--r--testapi/opnfv_testapi/resources/result_handlers.py19
-rw-r--r--testapi/opnfv_testapi/router/url_mappings.py3
-rw-r--r--testapi/opnfv_testapi/ui/auth/base.py35
-rw-r--r--testapi/opnfv_testapi/ui/auth/constants.py18
-rw-r--r--testapi/opnfv_testapi/ui/auth/sign.py80
-rw-r--r--testapi/opnfv_testapi/ui/auth/user.py43
-rw-r--r--testapi/opnfv_testapi/ui/root.py6
-rw-r--r--testapi/requirements.txt1
14 files changed, 104 insertions, 204 deletions
diff --git a/testapi/.gitignore b/testapi/.gitignore
index 00f8a03..86ec0d2 100644
--- a/testapi/.gitignore
+++ b/testapi/.gitignore
@@ -4,4 +4,4 @@ setup.cfg-e
opnfv_testapi/static
build
*.egg-info
-
+3rd_party/static/static
diff --git a/testapi/3rd_party/static/testapi-ui/components/profile/profile.html b/testapi/3rd_party/static/testapi-ui/components/profile/profile.html
index dc97c41..763f5d1 100644
--- a/testapi/3rd_party/static/testapi-ui/components/profile/profile.html
+++ b/testapi/3rd_party/static/testapi-ui/components/profile/profile.html
@@ -3,9 +3,16 @@
<div>
<table class="table table-striped table-hover">
<tbody>
- <tr> <td>User name</td> <td>{{auth.currentUser.fullname}}</td> </tr>
- <tr> <td>User OpenId</td> <td>{{auth.currentUser.openid}}</td> </tr>
+ <tr> <td>User</td> <td>{{auth.currentUser.user}}</td> </tr>
+ <tr> <td>Fullname</td> <td>{{auth.currentUser.fullname}}</td> </tr>
<tr> <td>Email</td> <td>{{auth.currentUser.email}}</td> </tr>
+ <tr> <td>Groups</td>
+ <td>
+ <div ng-repeat="group in auth.currentUser.groups">
+ {{group}}</br>
+ </div>
+ </td>
+ </tr>
</tbody>
</table>
</div>
diff --git a/testapi/3rd_party/static/testapi-ui/components/profile/profileController.js b/testapi/3rd_party/static/testapi-ui/components/profile/profileController.js
index 0660e19..5dbdf7b 100644
--- a/testapi/3rd_party/static/testapi-ui/components/profile/profileController.js
+++ b/testapi/3rd_party/static/testapi-ui/components/profile/profileController.js
@@ -26,7 +26,7 @@
* This is a provider for the user's uploaded public keys.
*/
function PubKeys($resource, testapiApiUrl) {
- return $resource(testapiApiUrl + '/profile/pubkeys/:id', null, null);
+ return $resource(testapiApiUrl + '/user/pubkeys/:id', null, null);
}
angular
diff --git a/testapi/etc/config.ini b/testapi/etc/config.ini
index 1ec899f..db0e191 100644
--- a/testapi/etc/config.ini
+++ b/testapi/etc/config.ini
@@ -21,48 +21,6 @@ authenticate = False
[ui]
url = http://localhost:8000
-[osid]
-
-# OpenStackID Auth Server URI. (string value)
-openstack_openid_endpoint = https://openstackid.org/accounts/openid2
-
-# OpenStackID logout URI. (string value)
-openid_logout_endpoint = https://openstackid.org/accounts/user/logout
-
-# Interaction mode. Specifies whether Openstack Id IdP may interact
-# with the user to determine the outcome of the request. (string
-# value)
-openid_mode = checkid_setup
-
-# Protocol version. Value identifying the OpenID protocol version
-# being used. This value should be "http://specs.openid.net/auth/2.0".
-# (string value)
-openid_ns = http://specs.openid.net/auth/2.0
-
-# Return endpoint in Refstack's API. Value indicating the endpoint
-# where the user should be returned to after signing in. Openstack Id
-# Idp only supports HTTPS address types. (string value)
-openid_return_to = v1/auth/signin_return
-
-# Claimed identifier. This value must be set to
-# "http://specs.openid.net/auth/2.0/identifier_select". or to user
-# claimed identity (user local identifier or user owned identity [ex:
-# custom html hosted on a owned domain set to html discover]). (string
-# value)
-openid_claimed_id = http://specs.openid.net/auth/2.0/identifier_select
-
-# Alternate identifier. This value must be set to
-# http://specs.openid.net/auth/2.0/identifier_select. (string value)
-openid_identity = http://specs.openid.net/auth/2.0/identifier_select
-
-# Indicates request for user attribute information. This value must be
-# set to "http://openid.net/extensions/sreg/1.1". (string value)
-openid_ns_sreg = http://openid.net/extensions/sreg/1.1
-
-# Comma-separated list of field names which, if absent from the
-# response, will prevent the Consumer from completing the registration
-# without End User interation. The field names are those that are
-# specified in the Response Format, with the "openid.sreg." prefix
-# removed. Valid values include: "country", "email", "firstname",
-# "language", "lastname" (string value)
-openid_sreg_required = email,fullname
+[lfid]
+# Linux Foundation cas URL
+cas_url = https://identity.linuxfoundation.org/cas/
diff --git a/testapi/opnfv_testapi/common/check.py b/testapi/opnfv_testapi/common/check.py
index 24ba876..009d3d4 100644
--- a/testapi/opnfv_testapi/common/check.py
+++ b/testapi/opnfv_testapi/common/check.py
@@ -8,14 +8,49 @@
##############################################################################
import functools
+import cas
from tornado import gen
from tornado import web
+from opnfv_testapi.common import constants
from opnfv_testapi.common import message
from opnfv_testapi.common import raises
+from opnfv_testapi.common.config import CONF
from opnfv_testapi.db import api as dbapi
+def login(method):
+ @web.asynchronous
+ @gen.coroutine
+ @functools.wraps(method)
+ def wrapper(self, *args, **kwargs):
+ ticket = self.get_query_argument('ticket', default=None)
+ if ticket:
+ client = cas.CASClient(version='2',
+ server_url=CONF.lfid_cas_url,
+ service_url=CONF.ui_url)
+ (user, attrs, _) = client.verify_ticket(ticket=ticket)
+ print 'login user: {}'.format(user)
+ login_user = {
+ 'user': user,
+ 'email': attrs.get('mail'),
+ 'fullname': attrs.get('field_lf_full_name'),
+ 'groups': constants.TESTAPI_USERS + attrs.get('group', [])
+ }
+ q_user = {'user': user}
+ db_user = yield dbapi.db_find_one(constants.USER_TABLE, q_user)
+ if not db_user:
+ dbapi.db_save(constants.USER_TABLE, login_user)
+ else:
+ dbapi.db_update(constants.USER_TABLE, q_user, login_user)
+
+ self.clear_cookie(constants.TESTAPI_ID)
+ self.set_secure_cookie(constants.TESTAPI_ID, user)
+ ret = yield gen.coroutine(method)(self, *args, **kwargs)
+ raise gen.Return(ret)
+ return wrapper
+
+
def authenticate(method):
@web.asynchronous
@gen.coroutine
diff --git a/testapi/opnfv_testapi/common/constants.py b/testapi/opnfv_testapi/common/constants.py
new file mode 100644
index 0000000..b37ebb3
--- /dev/null
+++ b/testapi/opnfv_testapi/common/constants.py
@@ -0,0 +1,5 @@
+TESTAPI_ID = 'testapi_id'
+CSRF_TOKEN = 'csrf_token'
+ROLE = 'role'
+TESTAPI_USERS = ['opnfv-testapi-users']
+USER_TABLE = 'users'
diff --git a/testapi/opnfv_testapi/resources/result_handlers.py b/testapi/opnfv_testapi/resources/result_handlers.py
index 9389d26..e202f5c 100644
--- a/testapi/opnfv_testapi/resources/result_handlers.py
+++ b/testapi/opnfv_testapi/resources/result_handlers.py
@@ -6,20 +6,20 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-import logging
-from datetime import datetime
-from datetime import timedelta
import json
+import logging
from bson import objectid
+from datetime import datetime
+from datetime import timedelta
-from opnfv_testapi.common.config import CONF
+from opnfv_testapi.common import constants
from opnfv_testapi.common import message
from opnfv_testapi.common import raises
+from opnfv_testapi.common.config import CONF
from opnfv_testapi.resources import handlers
from opnfv_testapi.resources import result_models
from opnfv_testapi.tornado_swagger import swagger
-from opnfv_testapi.ui.auth import constants as auth_const
class GenericResultHandler(handlers.GenericApiHandler):
@@ -59,13 +59,12 @@ class GenericResultHandler(handlers.GenericApiHandler):
elif k == 'to':
date_range.update({'$lt': str(v)})
elif k == 'signed':
- openid = self.get_secure_cookie(auth_const.OPENID)
- role = self.get_secure_cookie(auth_const.ROLE)
- logging.info('role:%s', role)
+ username = self.get_secure_cookie(constants.TESTAPI_ID)
+ role = self.get_secure_cookie(constants.ROLE)
if role:
del query['public']
if role != "reviewer":
- query['user'] = openid
+ query['user'] = username
elif k not in ['last', 'page', 'descend']:
query[k] = v
if date_range:
@@ -246,7 +245,7 @@ class ResultsUploadHandler(ResultsCLHandler):
self.json_args = json.loads(fileinfo['body']).copy()
self.json_args['public'] = is_public
- openid = self.get_secure_cookie(auth_const.OPENID)
+ openid = self.get_secure_cookie(constants.TESTAPI_ID)
if openid:
self.json_args['user'] = openid
diff --git a/testapi/opnfv_testapi/router/url_mappings.py b/testapi/opnfv_testapi/router/url_mappings.py
index 3e3ab87..be6240e 100644
--- a/testapi/opnfv_testapi/router/url_mappings.py
+++ b/testapi/opnfv_testapi/router/url_mappings.py
@@ -76,8 +76,7 @@ mappings = [
(r'/', root.RootHandler),
(r'/api/v1/auth/signin', sign.SigninHandler),
- (r'/api/v1/auth/signin_return', sign.SigninReturnHandler),
(r'/api/v1/auth/signout', sign.SignoutHandler),
- (r'/api/v1/profile', user.ProfileHandler),
+ (r'/api/v1/profile', user.UserHandler),
]
diff --git a/testapi/opnfv_testapi/ui/auth/base.py b/testapi/opnfv_testapi/ui/auth/base.py
deleted file mode 100644
index bea87c4..0000000
--- a/testapi/opnfv_testapi/ui/auth/base.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import random
-import string
-
-from six.moves.urllib import parse
-
-from opnfv_testapi.resources import handlers
-
-
-class BaseHandler(handlers.GenericApiHandler):
- def __init__(self, application, request, **kwargs):
- super(BaseHandler, self).__init__(application, request, **kwargs)
- self.table = 'users'
-
- def set_cookies(self, cookies):
- for cookie_n, cookie_v in cookies:
- self.set_secure_cookie(cookie_n, cookie_v)
-
-
-def get_token(length=30):
- """Get random token."""
- return ''.join(random.choice(string.ascii_lowercase)
- for i in range(length))
-
-
-def set_query_params(url, params):
- """Set params in given query."""
- url_parts = parse.urlparse(url)
- url = parse.urlunparse((
- url_parts.scheme,
- url_parts.netloc,
- url_parts.path,
- url_parts.params,
- parse.urlencode(params),
- url_parts.fragment))
- return url
diff --git a/testapi/opnfv_testapi/ui/auth/constants.py b/testapi/opnfv_testapi/ui/auth/constants.py
deleted file mode 100644
index 44ccb46..0000000
--- a/testapi/opnfv_testapi/ui/auth/constants.py
+++ /dev/null
@@ -1,18 +0,0 @@
-OPENID = 'openid'
-ROLE = 'role'
-DEFAULT_ROLE = 'user'
-
-# OpenID parameters
-OPENID_MODE = 'openid.mode'
-OPENID_NS = 'openid.ns'
-OPENID_RETURN_TO = 'openid.return_to'
-OPENID_CLAIMED_ID = 'openid.claimed_id'
-OPENID_IDENTITY = 'openid.identity'
-OPENID_REALM = 'openid.realm'
-OPENID_NS_SREG = 'openid.ns.sreg'
-OPENID_NS_SREG_REQUIRED = 'openid.sreg.required'
-OPENID_NS_SREG_EMAIL = 'openid.sreg.email'
-OPENID_NS_SREG_FULLNAME = 'openid.sreg.fullname'
-OPENID_ERROR = 'openid.error'
-
-CSRF_TOKEN = 'csrf_token'
diff --git a/testapi/opnfv_testapi/ui/auth/sign.py b/testapi/opnfv_testapi/ui/auth/sign.py
index 4623952..01cd0f7 100644
--- a/testapi/opnfv_testapi/ui/auth/sign.py
+++ b/testapi/opnfv_testapi/ui/auth/sign.py
@@ -1,76 +1,22 @@
-from six.moves.urllib import parse
-from tornado import gen
-from tornado import web
+from cas import CASClient
+from opnfv_testapi.common import constants
from opnfv_testapi.common.config import CONF
-from opnfv_testapi.db import api as dbapi
-from opnfv_testapi.ui.auth import base
-from opnfv_testapi.ui.auth import constants as const
+from opnfv_testapi.resources import handlers
-class SigninHandler(base.BaseHandler):
+class SigninHandler(handlers.GenericApiHandler):
def get(self):
- csrf_token = base.get_token()
- return_endpoint = parse.urljoin(CONF.api_url,
- CONF.osid_openid_return_to)
- return_to = base.set_query_params(return_endpoint,
- {const.CSRF_TOKEN: csrf_token})
+ client = CASClient(version='2',
+ server_url=CONF.lfid_cas_url,
+ service_url=CONF.ui_url)
+ self.redirect(url=(client.get_login_url()))
- params = {
- const.OPENID_MODE: CONF.osid_openid_mode,
- const.OPENID_NS: CONF.osid_openid_ns,
- const.OPENID_RETURN_TO: return_to,
- const.OPENID_CLAIMED_ID: CONF.osid_openid_claimed_id,
- const.OPENID_IDENTITY: CONF.osid_openid_identity,
- const.OPENID_REALM: CONF.api_url,
- const.OPENID_NS_SREG: CONF.osid_openid_ns_sreg,
- const.OPENID_NS_SREG_REQUIRED: CONF.osid_openid_sreg_required,
- }
- url = CONF.osid_openstack_openid_endpoint
- url = base.set_query_params(url, params)
- self.redirect(url=url, permanent=False)
-
-class SigninReturnHandler(base.BaseHandler):
- @web.asynchronous
- @gen.coroutine
- def get(self):
- if self.get_query_argument(const.OPENID_MODE) == 'cancel':
- self._auth_failure('Authentication canceled.')
-
- openid = self.get_query_argument(const.OPENID_CLAIMED_ID)
- role = const.DEFAULT_ROLE
- new_user_info = {
- 'openid': openid,
- 'email': self.get_query_argument(const.OPENID_NS_SREG_EMAIL),
- 'fullname': self.get_query_argument(const.OPENID_NS_SREG_FULLNAME),
- const.ROLE: role
- }
- user = yield dbapi.db_find_one(self.table, {'openid': openid})
- if not user:
- dbapi.db_save(self.table, new_user_info)
- else:
- role = user.get(const.ROLE)
-
- self.clear_cookie(const.OPENID)
- self.clear_cookie(const.ROLE)
- self.set_secure_cookie(const.OPENID, openid)
- self.set_secure_cookie(const.ROLE, role)
- self.redirect(url=CONF.ui_url)
-
- def _auth_failure(self, message):
- params = {'message': message}
- url = parse.urljoin(CONF.ui_url,
- '/#/auth_failure?' + parse.urlencode(params))
- self.redirect(url)
-
-
-class SignoutHandler(base.BaseHandler):
+class SignoutHandler(handlers.GenericApiHandler):
def get(self):
"""Handle signout request."""
- self.clear_cookie(const.OPENID)
- self.clear_cookie(const.ROLE)
- params = {'openid_logout': CONF.osid_openid_logout_endpoint}
- url = parse.urljoin(CONF.ui_url,
- '/#/logout?' + parse.urlencode(params))
- self.redirect(url)
+ self.clear_cookie(constants.TESTAPI_ID)
+ client = CASClient(version='2',
+ server_url=CONF.lfid_cas_url)
+ self.redirect(url=(client.get_logout_url(redirect_url=CONF.ui_url)))
diff --git a/testapi/opnfv_testapi/ui/auth/user.py b/testapi/opnfv_testapi/ui/auth/user.py
index 955cdee..ab86007 100644
--- a/testapi/opnfv_testapi/ui/auth/user.py
+++ b/testapi/opnfv_testapi/ui/auth/user.py
@@ -1,25 +1,26 @@
-from tornado import gen
-from tornado import web
-
+from opnfv_testapi.common import constants
from opnfv_testapi.common import raises
-from opnfv_testapi.db import api as dbapi
-from opnfv_testapi.ui.auth import base
+from opnfv_testapi.resources import handlers
+from opnfv_testapi.resources import models
+
+
+class User(models.ModelBase):
+ def __init__(self, user=None, email=None, fullname=None, groups=None):
+ self.user = user
+ self.email = email
+ self.fullname = fullname
+ self.groups = groups
+
+class UserHandler(handlers.GenericApiHandler):
+ def __init__(self, application, request, **kwargs):
+ super(UserHandler, self).__init__(application, request, **kwargs)
+ self.table = 'users'
+ self.table_cls = User
-class ProfileHandler(base.BaseHandler):
- @web.asynchronous
- @gen.coroutine
def get(self):
- openid = self.get_secure_cookie('openid')
- if openid:
- try:
- user = yield dbapi.db_find_one(self.table, {'openid': openid})
- self.finish_request({
- "openid": user.get('openid'),
- "email": user.get('email'),
- "fullname": user.get('fullname'),
- "role": user.get('role', 'user')
- })
- except Exception:
- pass
- raises.Unauthorized('Unauthorized')
+ username = self.get_secure_cookie(constants.TESTAPI_ID)
+ if username:
+ self._get_one(query={'user': username})
+ else:
+ raises.Unauthorized('Unauthorized')
diff --git a/testapi/opnfv_testapi/ui/root.py b/testapi/opnfv_testapi/ui/root.py
index 5b2c922..069ad5e 100644
--- a/testapi/opnfv_testapi/ui/root.py
+++ b/testapi/opnfv_testapi/ui/root.py
@@ -1,10 +1,12 @@
-from opnfv_testapi.resources.handlers import GenericApiHandler
+from opnfv_testapi.common import check
from opnfv_testapi.common.config import CONF
+from opnfv_testapi.resources import handlers
-class RootHandler(GenericApiHandler):
+class RootHandler(handlers.GenericApiHandler):
def get_template_path(self):
return CONF.static_path
+ @check.login
def get(self):
self.render('testapi-ui/index.html')
diff --git a/testapi/requirements.txt b/testapi/requirements.txt
index 4b6f75c..fbd2e0e 100644
--- a/testapi/requirements.txt
+++ b/testapi/requirements.txt
@@ -8,3 +8,4 @@ tornado>=3.1,<=4.3 # Apache-2.0
epydoc>=0.3.1
six>=1.9.0 # MIT
motor # Apache-2.0
+python-cas