Skip to content
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

feat(passport-exp): handle expiration edge cases [PXP-9235] #988

Merged
merged 49 commits into from
Jan 26, 2022

Conversation

Avantol13
Copy link
Contributor

@Avantol13 Avantol13 commented Nov 29, 2021

PXP-9235

In order to better handle updating/expiration of authorization from Passports, this PR has number of pieces.

Adjusts overall architecture such that:

  1. usersync no longer updates visas
  2. Access Token Polling gets updated passport(s) for a user and updates authorization and visas. It also sets expiration for authorization.
  3. A frequently-running cronjob handles the removal of stale, expired visas in the database

This PR also adds a variety of refactoring and updating around the above 3 to consolidate code, clarify logic, and fix unit tests.

Relies on uc-cdis/cloud-automation#1806

New Features

  • usersync no longer updates visas and Access Token Polling now both gets updated passport(s) for a user and updates authorization
  • A frequently-running cronjob handles the removal of expired visas

Breaking Changes

  • URL Signing when no_force_sign query param is provided: Previously Fence would make a decision based off if the data was public and no_force_sign provided. Fence will now NEVER sign if no_force_sign is provided (since the concept of "public" data has been abstracted out of Fence. Data access - public or not - is the sole responsibility of the policy engine). In other words, if no_force_sign is provided at the API level, Fence will respect that regardless of whether the resulting URL will actually work. The default Fence behavior should remain the same.

Bug Fixes

  • fix issue with anonymous Google signed URL generation (would fail with unauthenticated requests even if the data was supposed to be accessible)

Improvements

  • various refactoring around Passports

Dependency updates

Deployment changes

@Avantol13 Avantol13 marked this pull request as draft November 29, 2021 22:11
@github-actions
Copy link

The style in this PR agrees with black. ✔️

This formatting comment was generated automatically by a script in uc-cdis/wool.

@coveralls
Copy link

coveralls commented Nov 29, 2021

Pull Request Test Coverage Report for Build 12229

  • 254 of 303 (83.83%) changed or added relevant lines in 11 files are covered.
  • 51 unchanged lines in 8 files lost coverage.
  • Overall coverage decreased (-0.05%) to 72.493%

Changes Missing Coverage Covered Lines Changed/Added Lines %
fence/resources/openid/idp_oauth2.py 0 1 0.0%
fence/resources/openid/ras_oauth2.py 41 42 97.62%
fence/resources/ga4gh/passports.py 54 60 90.0%
fence/resources/google/utils.py 18 24 75.0%
fence/blueprints/data/indexd.py 62 69 89.86%
fence/blueprints/login/ras.py 7 14 50.0%
fence/scripting/fence_create.py 23 31 74.19%
fence/sync/sync_users.py 28 41 68.29%
Files with Coverage Reduction New Missed Lines %
fence/resources/openid/ras_oauth2.py 1 58.65%
fence/resources/admin/admin_projects.py 2 79.41%
fence/scripting/fence_create.py 2 57.58%
fence/sync/passport_sync/ras_sync.py 2 86.49%
fence/blueprints/login/ras.py 3 78.85%
fence/job/visa_update_cronjob.py 6 87.91%
fence/resources/userdatamodel/userdatamodel_project.py 9 59.26%
fence/sync/sync_users.py 26 73.54%
Totals Coverage Status
Change from base Build 12200: -0.05%
Covered Lines: 6681
Relevant Lines: 9216

💛 - Coveralls

@@ -46,10 +45,10 @@
get_google_app_creds,
give_service_account_billing_access_if_necessary,
)
from fence.resources.ga4gh.passports import get_gen3_users_from_ga4gh_passports
from fence.resources.ga4gh.passports import sync_gen3_users_authz_from_ga4gh_passports
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more descriptive to show that it's changing database and not just "get"-ing information

@@ -62,15 +61,21 @@

SUPPORTED_PROTOCOLS = ["s3", "http", "ftp", "https", "gs", "az"]
SUPPORTED_ACTIONS = ["upload", "download"]
ANONYMOUS_USER_ID = "anonymous"
ANONYMOUS_USER_ID = "-1"
Copy link
Contributor Author

@Avantol13 Avantol13 Dec 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fact that the user_id was not an integer was causing downstream validation problems since User.id is int in the database

@@ -517,12 +526,28 @@ def set_acls(self):
else:
raise Unauthorized("This file is not accessible")

def check_authz(self, action, user_ids_from_passports=None):
def get_authorized_and_user_id(self, action, user_ids_from_passports=None):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more descriptive / consistent return for this functionality

@@ -37,76 +39,52 @@ def __init__(self):
)

def post_login(self, user=None, token_result=None, id_from_idp=None):
# TODO: I'm not convinced this code should be in post_login.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for this file, the goal was to reduce duplication and replace this additional custom logic with the already built sync_gen3_users_authz_from_ga4gh_passports functionality as much as possible

@@ -270,91 +285,31 @@ def map_iss_sub_pair_to_user(self, issuer, subject_id, username, email):
return iss_sub_pair_to_user.user.username

@backoff.on_exception(backoff.expo, Exception, **DEFAULT_BACKOFF_SETTINGS)
def update_user_visas(self, user, pkey_cache, db_session=current_session):
def update_user_authorization(self, user, pkey_cache, db_session=current_session):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for this file, the goal was to reduce duplication and replace this additional custom logic with the already built sync_gen3_users_authz_from_ga4gh_passports functionality as much as possible

@@ -210,7 +239,6 @@ def init_syncer(
sync_from_local_yaml_file=None,
arborist=None,
folder=None,
sync_from_visas=False,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usersync no longer provides the option to sync from visas. This is handled entirely by the access token polling job

info["tags"] = {"dbgap_role": permission.get("role", "")}
else:
# Remove visas if its invalid or expired
user.ga4gh_visas_v1 = []
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't mess with db here, handle upstream

@@ -1954,196 +1952,24 @@ def parse_user_visas(self, db_session):

return (user_projects, user_info)

def _sync_visas(self, sess):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is handled entirely by access token polling and sync_gen3_users_authz_from_ga4gh_passports now

@@ -221,8 +221,8 @@ def add_visa_manually(db_session, user, rsa_private_key, kid):
"ga4gh_visa_v1": {
"type": "https://ras.nih.gov/visas/v1",
"asserted": int(time.time()),
"value": "https://nig/passport/dbgap",
"source": "https://ncbi/gap",
"value": "https://stsstg.nih.gov/passport/dbgap/v1.1",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of tests had to change so that the fake visas were actually "valid", since sync_gen3_users_authz_from_ga4gh_passports validates all the Visas

return self.public_authz
else:
return self.public_acl

@cached_property
def public_acl(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need this for some backwards compatibility

("upload", 5, None, False, "fake conn str", "some user", False, False),
("upload", 5, True, None, "fake conn str", ANONYMOUS_USER_ID, True, False),
("upload", 5, True, None, "fake conn str", ANONYMOUS_USER_ID, False, False),
("download", 5, None, "fake conn str", "some user", False, False),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove public_data as an option, remove duplicate tests, and adjust expected behavior to meet new expectations. See "Breaking Changes" in the PR description

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the swagger doc could be updated too?

@Avantol13 Avantol13 changed the title feat(passport-exp): handle expiration edge cases feat(passport-exp): handle expiration edge cases [PXP-9235] Jan 24, 2022
users_from_passports = fence.resources.ga4gh.passports.sync_gen3_users_authz_from_ga4gh_passports(
[passport],
authz_policy_prefix="POST.LOGIN",
pkey_cache=pkey_cache,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried logging in and am getting: NameError: name 'pkey_cache' is not defined for this line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants