-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VADC-845 #1131
base: master
Are you sure you want to change the base?
VADC-845 #1131
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,14 @@ | |
|
||
from fence.blueprints.login.base import DefaultOAuth2Login, DefaultOAuth2Callback | ||
from fence.models import IdentityProvider | ||
from cdislogging import get_logger | ||
|
||
from fence.config import config | ||
from fence.blueprints.login.base import DefaultOAuth2Login, DefaultOAuth2Callback | ||
import fence.resources.cognito.groups | ||
from flask import current_app | ||
|
||
logger = get_logger(__name__) | ||
|
||
|
||
class CognitoLogin(DefaultOAuth2Login): | ||
|
@@ -16,3 +24,27 @@ def __init__(self): | |
super(CognitoCallback, self).__init__( | ||
idp_name=IdentityProvider.cognito, client=flask.current_app.cognito_client | ||
) | ||
|
||
def post_login(self, user=None, token_result=None, id_from_idp=None): | ||
userinfo = flask.g.userinfo | ||
|
||
email = userinfo.get("email") | ||
|
||
assign_groups_as_policies = config["cognito"]["assign_groups_as_policies"] | ||
assign_groups_claim_name = config["cognito"]["assign_groups_claim_name"] | ||
|
||
if assign_groups_as_policies: | ||
try: | ||
groups = flask.current_app.cognito_client.get_group_claims( | ||
userinfo, assign_groups_claim_name | ||
) | ||
except Exception as e: | ||
err_msg = "Could not retrieve groups" | ||
logger.error("{}: {}".format(e, err_msg)) | ||
raise | ||
|
||
fence.resources.cognito.groups.sync_gen3_users_authz_from_adfs_groups( | ||
email, groups, db_session=current_app.scoped_session() | ||
) | ||
|
||
super(CognitoCallback, self).post_login(id_from_idp=id_from_idp) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not just |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import fence.scripting.fence_create | ||
|
||
|
||
def sync_gen3_users_authz_from_adfs_groups(current_session, email, groups): | ||
""" | ||
Sync the authorization of users in the Gen3 database with the groups | ||
they are in on the ADFS server. | ||
Args: | ||
groups (list): list of groups to sync | ||
db_session (flask_sqlalchemy_session.SQLAlchemySession): db session to use | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. db_session is not part of this method's arguments |
||
Return: | ||
dict: dictionary of users that were synced and the groups they were | ||
synced with | ||
""" | ||
# for each group, assign current user the following resources: | ||
# /cohort-middleware/{group} | ||
# with both role_ids: 'cohort_middleware_admin' and 'cohort_middleware_outputs_admin_reader' | ||
db_session = db_session or current_session | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
_sync_adfs_groups( | ||
email, | ||
groups, | ||
db_session=db_session, | ||
) | ||
|
||
|
||
def _sync_adfs_groups(gen3_user, groups, current_session, db_session=None): | ||
db_session = db_session or current_session | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does not seem to be used? |
||
|
||
default_args = fence.scripting.fence_create.get_default_init_syncer_inputs( | ||
authz_provider="Cognito" | ||
) | ||
syncer = fence.scripting.fence_create.init_syncer(**default_args) | ||
|
||
groups = syncer.sync_single_user_groups( | ||
gen3_user, | ||
groups, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,25 @@ def get_auth_url(self): | |
|
||
return uri | ||
|
||
def get_group_claims(self, userinfo, claims): | ||
""" | ||
Return group claims from userinfo response | ||
Args: | ||
userinfo (dict): userinfo response | ||
Return: | ||
str: list of groups | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this a single string (e.g. a comma-separated list)? If yes, where is is split into a real list? |
||
""" | ||
result = None | ||
|
||
attributes = userinfo.get("Attributes") | ||
if attributes and len(attributes) > 0: | ||
for a in attributes: | ||
if a["Name"] == "custom:groups": | ||
result = a["Value"] | ||
break | ||
|
||
return result | ||
|
||
def get_auth_info(self, code): | ||
""" | ||
Exchange code for tokens, get email from id token claims. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2520,3 +2520,56 @@ def sync_single_user_visas(self, user, ga4gh_visas, sess=None, expires=None): | |
self.logger.error("No arborist client set; skipping arborist sync") | ||
|
||
return parsed_visas | ||
|
||
def sync_single_user_groups(self, user, groups, sess=None): | ||
""" | ||
Sync a single user's groups during login | ||
Args: | ||
user (userdatamodel.user.User): Fence user whose group | ||
authz info is being synced | ||
groups (list): a list of groups that the user is a member of | ||
Return: | ||
list of successfully assigned groups | ||
""" | ||
try: | ||
user_yaml = UserYAML.from_file( | ||
self.sync_from_local_yaml_file, encrypted=False, logger=self.logger | ||
) | ||
except (EnvironmentError, AssertionError) as e: | ||
self.logger.error(str(e)) | ||
self.logger.error("aborting early") | ||
raise | ||
|
||
user_projects = dict() | ||
projects = {} | ||
|
||
for group in groups: | ||
project = {} | ||
privileges = {"read-storage", "read"} | ||
project[group] = privileges | ||
projects = {**projects, **project} | ||
|
||
user_projects[user.username] = projects | ||
user_projects = self.parse_projects(user_projects) | ||
|
||
# update arborist db (user access) | ||
if self.arborist_client: | ||
self.logger.info("Synchronizing arborist with authorization info...") | ||
success = self._update_authz_in_arborist( | ||
sess, | ||
user_projects, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is for another feature in Gen3, not related to "team projects" and not reusable as such. Can you please check? |
||
user_yaml=user_yaml, | ||
single_user_sync=True, | ||
) | ||
if success: | ||
self.logger.info( | ||
"Finished synchronizing authorization info to arborist" | ||
) | ||
else: | ||
self.logger.error( | ||
"Could not synchronize authorization info successfully to arborist" | ||
) | ||
else: | ||
self.logger.error("No arborist client set; skipping arborist sync") | ||
|
||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
token_result
is actually used in super.post_login(). Why is it not passed?