Skip to content

Commit

Permalink
InCommon login (#703)
Browse files Browse the repository at this point in the history
- Support InCommon login: add "idp" and "shib_idp" query parameters to "/login/shib", "/login/fence" and "/authorize"
- Fence config ENABLED_IDENTITY_PROVIDERS: "providers" field deprecated and replaced by "login_options" to allow enabling several login options for the same provider (backwards compatible)
  • Loading branch information
paulineribeyre authored Oct 15, 2019
1 parent c1223c2 commit 4d12f0c
Show file tree
Hide file tree
Showing 16 changed files with 483 additions and 161 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Fence is a core service of the Gen3 stack that has multiple capabilities:

1. [API Documentation](#API-documentation)
1. [Terminologies](#Terminologies)
1. [Identity Providers](#identity-provider)
1. [Identity Providers](#identity-providers)
1. [OIDC & OAuth2](#oidc--oauth2)
1. [Accessing Data](#accessing-data)
1. [Setup](#setup)
Expand Down Expand Up @@ -95,13 +95,11 @@ Relying Party - an OAuth 2.0 Client which uses (requests) OpenID Connect.
Fence can be configured to support different Identity Providers (IdPs) for AuthN.
At the moment, supported IDPs include:
- Google
- Shibboleth
- [Shibboleth](docs/shibboleth.md)
- NIH iTrust
- InCommon
- eduGAIN

Note: the Shibboleth dockerfile image is at https://quay.io/repository/cdis/fence-shib and is NOT compatible with python 3/the latest fence.

## OIDC & OAuth2

Fence acts as a central broker that supports multiple IdPs.
Expand Down
12 changes: 6 additions & 6 deletions docs/google_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Google supports a bucket-level configuration called ["Requester Pays"](https://c

> Without requester pays enabled, the Google project the Google Bucket is in gets billed.
The Data Access methods [Signed URLs](#signed-urls) and [Temporary Service Account Credentials](#temporary-service-account-credentials) support accessing requester pays buckets with some additional configuration and considerations (noteably: how it affects end-users).
The Data Access methods [Signed URLs](#signed-urls) and [Temporary Service Account Credentials](#temporary-service-account-credentials) support accessing requester pays buckets with some additional configuration and considerations (notably: how it affects end-users).

In order to fully understand the options for requester pays support, it's important to first understand the technical steps to get any of these Google Data Access methods to work, as detailed in the library Fence uses for Google API interactions, [cirrus](https://github.com/uc-cdis/cirrus). It would also be useful to read through the access method details for [Signed URLs](#signed-urls) and [Temporary Service Account Credentials](#temporary-service-account-credentials).

Expand Down Expand Up @@ -133,7 +133,7 @@ If you want Fence to automatically attempt to provide the necessary permissions
Example for Google's Cloud Storage SDK `gsutil`:

```bash
# activate the temporary service account credentials recieved from Fence
# activate the temporary service account credentials received from Fence
# this assumes the creds are saved in a file named `creds.json`
gcloud auth activate-service-account --key-file ./creds.json

Expand Down Expand Up @@ -179,7 +179,7 @@ Each Client Service Account is a member in the User's Proxy Group, meaning it ha

> WARNING: By default, Google Service Account Keys have an expiration of 10 years. To create a more manageable and secure expiration you must manually "expire" the keys by deleting them with a cronjob (once they are alive longer than a configured expiration). Fence's command line tool `fence-create` has a function for expiring keys that you should run on a schedule. Check out `fence-create google-manage-keys --help`
Note that internally, we handle users themselves generating these temporary credentials differently. A user is given a **Primary Service Account** which is essentially the same thing as a Client Service Account, but is meant for use solely by the user themself (e.g. not going through a client or outside applcation but hitting the API directly).
Note that internally, we handle users themselves generating these temporary credentials differently. A user is given a **Primary Service Account** which is essentially the same thing as a Client Service Account, but is meant for use solely by the user themself (e.g. not going through a client or outside application but hitting the API directly).

At the moment, we track keys generated for the Primary Service Account in our db. Client Service Accounts are expired by checking their creation time through Google's API.

Expand Down Expand Up @@ -207,7 +207,7 @@ A user logs into fence with their eRA Commons ID. To get access to data through
---

Google Account Linking is achieved by sending the user through the beginning of the OIDC flow with Google. The user is redirected to a Google Login page and whichever account they succesfully log in to becomes linked to their fence identity.
Google Account Linking is achieved by sending the user through the beginning of the OIDC flow with Google. The user is redirected to a Google Login page and whichever account they successfully log in to becomes linked to their fence identity.

![Google Account Linking](images/g_accnt_link.png)

Expand All @@ -227,7 +227,7 @@ This allows a user to create their own personal Google Cloud Project and registe

This method also requires Fence to have access to that user's Google project. Fence is then able to monitor the project for any anomalies that may unintentionally provide data access to entities who should not have access.

In order to register a Service Account, *all* users in the Google Project must have already gone through Google Account Linking (as desribed above). After that, any user on the project can attempt to register a service account with fence.
In order to register a Service Account, *all* users in the Google Project must have already gone through Google Account Linking (as described above). After that, any user on the project can attempt to register a service account with fence.

---

Expand All @@ -247,7 +247,7 @@ Projects are always validated against the following checks:
* Checks if the Google project either has no parent organization, or if it does, it is included on the whitelist of parent organizations (defined in Fence config). (The reason for this logic is that user permissions can be inherited from a parent organization, but the Fence SA is only given permission on the project level and thus can only read project-specific IAM policies. Any inherited policies will not be available during validation. Therefore, if there is no parent org then there is nothing to worry about, but if there is, then we must trust the parent org to have properly set its permissions.)
* Google Project only has valid member types
* Key: `valid_member_types`
* Checks if the Google project ony has members that are User Accounts or Service Accounts.
* Checks if the Google project only has members that are User Accounts or Service Accounts.
* Google Project members exist in fence
* Key: `members_exist_in_fence`
* Checks if the User members on the Google project exist in the fence DB
Expand Down
8 changes: 7 additions & 1 deletion fence/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,13 @@ def _set_authlib_cfgs(app):


def _setup_oidc_clients(app):
enabled_idp_ids = list(config["ENABLED_IDENTITY_PROVIDERS"]["providers"].keys())
if "LOGIN_OPTIONS" in config:
enabled_idp_ids = [option["idp"] for option in config["LOGIN_OPTIONS"]]
else:
# fall back on "providers"
enabled_idp_ids = list(
config.get("ENABLED_IDENTITY_PROVIDERS", {}).get("providers", {}).keys()
)
oidc = config.get("OPENID_CONNECT", {})

# Add OIDC client for Google if configured.
Expand Down
11 changes: 10 additions & 1 deletion fence/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,16 @@ def wrapper(*args, **kwargs):
return f(*args, **kwargs)

eppn = None
enable_shib = "shibboleth" in config.get("ENABLED_IDENTITY_PROVIDERS", [])
if "LOGIN_OPTIONS" in config:
enable_shib = "shibboleth" in [
option["idp"] for option in config["LOGIN_OPTIONS"]
]
else:
# fall back on "providers"
enable_shib = "shibboleth" in config.get(
"ENABLED_IDENTITY_PROVIDERS", {}
).get("providers", {})

if enable_shib and "SHIBBOLETH_HEADER" in config:
eppn = flask.request.headers.get(config["SHIBBOLETH_HEADER"])

Expand Down
Loading

0 comments on commit 4d12f0c

Please sign in to comment.