Merge pull request #75 from dod-ccpo/authz-permissions

Authz permissions
This commit is contained in:
dandds 2018-07-18 09:44:46 -04:00 committed by GitHub
commit 7d3cd04bdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 89 additions and 28 deletions

View File

@ -26,7 +26,7 @@ def make_app(config, deps, **kwargs):
url( url(
r"/login-redirect", r"/login-redirect",
LoginRedirect, LoginRedirect,
{"sessions": deps["sessions"], "authnid_client": deps["authnid_client"]}, {"sessions": deps["sessions"], "authnid_client": deps["authnid_client"], "authz_client": deps["authz_client"]},
name="login_redirect", name="login_redirect",
), ),
url(r"/home", Main, {"page": "home"}, name="home"), url(r"/home", Main, {"page": "home"}, name="home"),
@ -88,7 +88,7 @@ def make_app(config, deps, **kwargs):
url( url(
r"/login-dev", r"/login-dev",
Dev, Dev,
{"action": "login", "sessions": deps["sessions"]}, {"action": "login", "sessions": deps["sessions"], "authz_client": deps["authz_client"]},
name="dev-login", name="dev-login",
) )
] ]

View File

@ -6,16 +6,26 @@ helpers = {"assets": environment}
class BaseHandler(tornado.web.RequestHandler): class BaseHandler(tornado.web.RequestHandler):
def get_template_namespace(self): def get_template_namespace(self):
ns = super(BaseHandler, self).get_template_namespace() ns = super(BaseHandler, self).get_template_namespace()
helpers["config"] = self.application.config helpers["config"] = self.application.config
ns.update(helpers) ns.update(helpers)
return ns return ns
@tornado.gen.coroutine
def login(self, user): def login(self, user):
user["atat_permissions"] = yield self._get_user_permissions(user["id"])
session_id = self.sessions.start_session(user) session_id = self.sessions.start_session(user)
self.set_secure_cookie("atat", session_id) self.set_secure_cookie("atat", session_id)
self.redirect("/home") return self.redirect("/home")
@tornado.gen.coroutine
def _get_user_permissions(self, user_id):
response = yield self.authz_client.post(
"/users", json={"id": user_id, "atat_role": "ccpo"}
)
return response.json["atat_permissions"]
def get_current_user(self): def get_current_user(self):
cookie = self.get_secure_cookie("atat") cookie = self.get_secure_cookie("atat")
@ -25,6 +35,7 @@ class BaseHandler(tornado.web.RequestHandler):
except SessionNotFoundError: except SessionNotFoundError:
self.clear_cookie("atat") self.clear_cookie("atat")
return None return None
else: else:
return None return None

View File

@ -1,15 +1,19 @@
import tornado.gen
from atst.handler import BaseHandler from atst.handler import BaseHandler
class Dev(BaseHandler): class Dev(BaseHandler):
def initialize(self, action, sessions): def initialize(self, action, sessions, authz_client):
self.action = action self.action = action
self.sessions = sessions self.sessions = sessions
self.authz_client = authz_client
@tornado.gen.coroutine
def get(self): def get(self):
user = { user = {
"id": "164497f6-c1ea-4f42-a5ef-101da278c012", "id": "164497f6-c1ea-4f42-a5ef-101da278c012",
"first_name": "Test", "first_name": "Test",
"last_name": "User" "last_name": "User",
} }
self.login(user) yield self.login(user)

View File

@ -3,9 +3,10 @@ from atst.handler import BaseHandler
class LoginRedirect(BaseHandler): class LoginRedirect(BaseHandler):
def initialize(self, authnid_client, sessions): def initialize(self, authnid_client, sessions, authz_client):
self.authnid_client = authnid_client self.authnid_client = authnid_client
self.sessions = sessions self.sessions = sessions
self.authz_client = authz_client
@tornado.gen.coroutine @tornado.gen.coroutine
def get(self): def get(self):
@ -13,7 +14,7 @@ class LoginRedirect(BaseHandler):
if token: if token:
user = yield self._fetch_user_info(token) user = yield self._fetch_user_info(token)
if user: if user:
self.login(user) yield self.login(user)
else: else:
self.write_error(401) self.write_error(401)

View File

@ -27,9 +27,17 @@ class Request(BaseHandler):
@tornado.gen.coroutine @tornado.gen.coroutine
def get(self): def get(self):
user = self.get_current_user() user = self.get_current_user()
response = yield self.requests_client.get( requests = yield self.fetch_requests(user)
"/users/{}/requests".format(user["id"])
)
requests = response.json["requests"]
mapped_requests = [map_request(user, request) for request in requests] mapped_requests = [map_request(user, request) for request in requests]
self.render("requests.html.to", page=self.page, requests=mapped_requests) self.render("requests.html.to", page=self.page, requests=mapped_requests)
@tornado.gen.coroutine
def fetch_requests(self, user):
if "review_and_approve_jedi_workspace_request" in user["atat_permissions"]:
response = yield self.requests_client.get("/requests")
else:
response = yield self.requests_client.get(
"/requests?creator_id={}".format(user["id"])
)
return response.json["requests"]

View File

@ -53,9 +53,7 @@ class RequestNew(BaseHandler):
if request_id: if request_id:
response = yield self.requests_client.get( response = yield self.requests_client.get(
"/users/{}/requests/{}".format( "/requests/{}".format(request_id),
self.get_current_user()["id"], request_id
),
raise_error=False, raise_error=False,
) )
if response.ok: if response.ok:
@ -77,14 +75,6 @@ class RequestNew(BaseHandler):
can_submit=jedi_flow.can_submit can_submit=jedi_flow.can_submit
) )
@tornado.gen.coroutine
def get_request(self, request_id):
request = yield self.requests_client.get(
"/users/{}/requests/{}".format(self.get_current_user()["id"], request_id),
raise_error=False,
)
return request
class JEDIRequestFlow(object): class JEDIRequestFlow(object):
def __init__( def __init__(

View File

@ -2,7 +2,7 @@
PORT=8000 PORT=8000
ENVIRONMENT = dev ENVIRONMENT = dev
DEBUG = true DEBUG = true
AUTHZ_BASE_URL = http://localhost AUTHZ_BASE_URL = http://localhost:8002
AUTHNID_BASE_URL= https://localhost:8001 AUTHNID_BASE_URL= https://localhost:8001
COOKIE_SECRET = some-secret-please-replace COOKIE_SECRET = some-secret-please-replace
SECRET = change_me_into_something_secret SECRET = change_me_into_something_secret

View File

@ -1,14 +1,14 @@
import pytest import pytest
from atst.app import make_app, make_deps, make_config from atst.app import make_app, make_deps, make_config
from tests.mocks import MockApiClient, MockRequestsClient from tests.mocks import MockApiClient, MockRequestsClient, MockAuthzClient
from atst.sessions import DictSessions from atst.sessions import DictSessions
@pytest.fixture @pytest.fixture
def app(): def app():
TEST_DEPS = { TEST_DEPS = {
"authz_client": MockApiClient("authz"), "authz_client": MockAuthzClient("authz"),
"requests_client": MockRequestsClient("requests"), "requests_client": MockRequestsClient("requests"),
"authnid_client": MockApiClient("authnid"), "authnid_client": MockApiClient("authnid"),
"sessions": DictSessions(), "sessions": DictSessions(),

View File

@ -49,7 +49,7 @@ class MockRequestsClient(MockApiClient):
"id": "66b8ef71-86d3-48ef-abc2-51bfa1732b6b", "id": "66b8ef71-86d3-48ef-abc2-51bfa1732b6b",
"creator": "49903ae7-da4a-49bf-a6dc-9dff5d004238", "creator": "49903ae7-da4a-49bf-a6dc-9dff5d004238",
"body": {}, "body": {},
"status": "incomplete" "status": "incomplete",
} }
return self._get_response("GET", path, 200, json=json) return self._get_response("GET", path, 200, json=json)
@ -61,3 +61,47 @@ class MockRequestsClient(MockApiClient):
"body": {}, "body": {},
} }
return self._get_response("POST", path, 202, json=json) return self._get_response("POST", path, 202, json=json)
class MockAuthzClient(MockApiClient):
@tornado.gen.coroutine
def post(self, path, **kwargs):
json = {
"atat_permissions": [
"view_original_jedi_request",
"review_and_approve_jedi_workspace_request",
"modify_atat_role_permissions",
"create_csp_role",
"delete_csp_role",
"deactivate_csp_role",
"modify_csp_role_permissions",
"view_usage_report",
"view_usage_dollars",
"add_and_assign_csp_roles",
"remove_csp_roles",
"request_new_csp_role",
"assign_and_unassign_atat_role",
"view_assigned_atat_role_configurations",
"view_assigned_csp_role_configurations",
"deactivate_workspace",
"view_atat_permissions",
"transfer_ownership_of_workspace",
"add_application_in_workspace",
"delete_application_in_workspace",
"deactivate_application_in_workspace",
"view_application_in_workspace",
"rename_application_in_workspace",
"add_environment_in_application",
"delete_environment_in_application",
"deactivate_environment_in_application",
"view_environment_in_application",
"rename_environment_in_application",
"add_tag_to_workspace",
"remove_tag_from_workspace",
],
"atat_role": "ccpo",
"id": "164497f6-c1ea-4f42-a5ef-101da278c012",
"username": None,
"workspace_roles": [],
}
return self._get_response("POST", path, 200, json=json)

View File

@ -3,7 +3,7 @@ import pytest
import tornado.web import tornado.web
import tornado.gen import tornado.gen
MOCK_USER = {"user": {"id": "438567dd-25fa-4d83-a8cc-8aa8366cb24a"}} MOCK_USER = {"id": "438567dd-25fa-4d83-a8cc-8aa8366cb24a"}
@tornado.gen.coroutine @tornado.gen.coroutine
def _fetch_user_info(c, t): def _fetch_user_info(c, t):
return MOCK_USER return MOCK_USER
@ -76,3 +76,6 @@ def test_valid_login_creates_session(app, monkeypatch, http_client, base_url):
raise_error=False, raise_error=False,
) )
assert len(app.sessions.sessions) == 1 assert len(app.sessions.sessions) == 1
session = list(app.sessions.sessions.values())[0]
assert "atat_permissions" in session["user"]
assert isinstance(session["user"]["atat_permissions"], list)