Skip to content

Commit

Permalink
Documentation update & small cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ponyisi committed Feb 26, 2025
1 parent 2aa8e55 commit 0c46452
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 54 deletions.
32 changes: 26 additions & 6 deletions docs/deployment/production.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,20 @@ since your grid certs will be usable by anyone on the Internet.

To prevent this, ServiceX supports an authentication system which requires
new users to create accounts with your ServiceX deployment by authenticating
to Globus with the identity provider of their choice
(such as CERN or their university).
to an OpenID Connect provider of your choice. Below we document setting it up for
Globus, but other providers can be set up with the same kind of configuration.

A system like Globus will provide authentication credentials for essentially
anyone, and you may not want all those people to have access to your instance. For
this reason, by default, there is an additional user approval step, also documented below.
However, if the authentication provider is such that getting credentials at all is
good enough to authorize the user to use ServiceX (for example, only members of a
certain experiment can authenticate), then this step can be skipped, by setting the following
in `values.yaml`:
```yaml
app:
allowAllAfterAuth: true
```


### Setting up Globus Auth
Expand All @@ -252,16 +264,25 @@ If you want to use port-forwarding, also include

Save the record.

For the configuration below, we can use the `values.yaml` or a secrets file. If it
is in the secrets, drop the `app` block.

We need to tell ServiceX to use the Globus OIDC endpoints:
```yaml
app:
oauthMetadataURL: "https://auth.globus.org/.well-known/openid-configuration"
```

Copy the Client ID and paste this into your `values.yaml`.
```yaml
app:
globusClientID: <Client ID here>
oauthClientID: <Client ID here>
```

Generate a Client Secret and paste this value into `values.yaml` as well:
```yaml
app:
globusClientSecret: <Client Secret here>
oauthClientSecret: <Client Secret here>
```

Finally, you can enable authentication in `values.yaml`:
Expand All @@ -273,8 +294,7 @@ app:

The system works as follows:
- New users will be required to create accounts with their Globus logins.
- New accounts will be pending, and cannot make requests until approved.
- Accounts must be approved by a ServiceX admin.
- Unless `allowAllAfterAuth` is enabled, new accounts will be pending, and cannot make requests until approved by a ServiceX admin.
- To bootstrap the initial admin account, you must set `app.adminEmail`
to the email address associated with the administrator's Globus account.

Expand Down
5 changes: 3 additions & 2 deletions docs/deployment/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ parameters for the [rabbitMQ](https://github.com/bitnami/charts/tree/master/bitn
| `app.rabbitmq.retry_interval` | Number of seconds to wait between RabbitMQ retries on startup | 10 |
| `app.replicas` | Number of App pods to start. Experimental! | 1 |
| `app.auth` | Enable authentication or allow unfettered access (Python boolean string) | `false` |
| `app.globusClientID` | Globus application Client ID | - |
| `app.globusClientSecret` | Globus application Client Secret | - |
| `app.oauthMetadataURL` | OpenID Connect provider well known configuration endpoint URL | - |
| `app.oauthClientID` | OpenID Connect application Client ID | - |
| `app.oauthClientSecret` | OpenID Connect application Client Secret | - |
| `app.adminEmail` | Email address for initial admin user | <admin@example.com> |
| `app.tokenExpires` | Seconds until the ServiceX API tokens (JWT refresh tokens) expire | False (never) |
| `app.authExpires` | Seconds until the JWT access tokens expire | 21600 (six hours) |
Expand Down
9 changes: 5 additions & 4 deletions docs/development/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ and retrieving status updates, and retrieving the results. It also has a set of
private in-cluster REST endpoints for orchestrating the microservices

It also serves a frontend web application where users can authenticate via
Globus and obtain ServiceX API tokens. Authentication is optional, and may be
OpenID Connect and obtain ServiceX API tokens. Authentication is optional, and may be
enabled on a per-deployment basis (see below for more details).

Potential roadmap features for the web frontend include a dashboard of current
Expand All @@ -114,13 +114,14 @@ refresh token) in their `servicex.yaml` file. The frontend Python client will
use this to obtain access tokens.

Users can obtain a ServiceX API token by visiting the frontend web application.
Users must authenticate by signing in to Globus via the identity provider of
choice. New accounts will be marked as pending, and can be approved by the
Users must authenticate by signing in to the configured OpenID Connect provider.
ServiceX can be set up to auto-accept new accounts, or to mark them as pending
approval by the
deployment's administrators. This can be done via Slack if the webhook is
configured. Once approved, new users will receive a welcome email via Mailgun
(if configured).

Future versions of ServiceX may support disabling Globus auth and the internal
Future versions of ServiceX may support disabling OIDC auth and the internal
user management system, but retaining the JWT system. ServiceX API Tokens would
need to be generated externally using the same secret used for the deployment.

Expand Down
5 changes: 2 additions & 3 deletions examples/ATLAS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ pip install jupyterlab-widgets

Visit SSL's [xAOD ServiceX](https://xaod.servicex.af.uchicago.edu) instance. Click
on the _Sign-in_ button in the upper right hand corner. You will be asked to
authenticate via GlobusAuth and complete a registration form. Once this form is
complete, it will be reviewed by SSL staff. You will receive an email upon
approval.
authenticate via the ATLAS SSO and complete a registration form. Once this form is
complete, your account will be created.

At this time you may return to the ServiceX page. Click on your name in the
upper right hand corner and then select _Profile_ tab. Click on the download
Expand Down
18 changes: 11 additions & 7 deletions servicex_app/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ user's identity) and authorization (control of access to API resources).

Authentication
**************
Authentication is currently implemented via `Globus <https://www.globus.org/>`_,
a federated identity provider which implements the OAuth 2.0 protocol.
Authentication is currently implemented via an interface to an OpenID Connect
provider of your choice. It has so far been tested with `Globus <https://www.globus.org/>` and Keycloak.
Prospective users must visit the ServiceX website included in this Flask app
at its hosted domain. There, they can sign in via Globus to confirm their
identity using any supported identity provider (e.g. their university, CILogon,
or GitHub account). A corresponding ServiceX user account will be created.
at its hosted domain. There, they can sign in via the OIDC provider.
A corresponding ServiceX user account will be created.
Existing users can also visit the website to view information associated with
their account.

Authorization
By default there is an additional step where new users need to be approved. If successful
authentication with the OIDC provider can be considered to constitute authorization to use
ServiceX as well, then this step can be skipped.

Authorization for Requests
*************
If authentication is enabled, API resources will be protected with JWT bearer
tokens. Authenticated users will be issued a ServiceX API token, which is a JWT
Expand All @@ -53,7 +56,8 @@ initial admin user. The first user to sign up with this email address will be
made an admin user automatically. This should be done immediately after
deployment.

New users are marked as pending, and will be unable to submit requests until
Unless the system is set up to auto-accept new users, new users are marked as pending,
and will be unable to submit requests until
approved. ServiceX admins can view the pending users with a GET on the
``/pending`` endpoint. They can approve a pending user with a POST to
``/accept`` with a body of:
Expand Down
23 changes: 1 addition & 22 deletions servicex_app/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion servicex_app/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ flask-jwt-extended = "^4.4.4"
passlib = "^1.7.4"
flask-sqlalchemy = "^3.0.2"
kubernetes = "^25.3.0"
globus-sdk = "^3.13.0"
cryptography = "^43.0.1"
bootstrap-flask = "^2.1.0"
blinker = "^1.5"
Expand Down
2 changes: 1 addition & 1 deletion servicex_app/servicex_app/web/sign_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@


def sign_in():
"""Send the user to Globus Auth."""
"""Send the user to OIDC Auth."""
return redirect(url_for('auth_callback'))
2 changes: 1 addition & 1 deletion servicex_app/servicex_app/web/sign_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@oauth_required
def sign_out():
"""Revoke tokens with Globus Auth and destroy session state."""
"""Revoke tokens with OIDC and destroy session state."""
from authlib.integrations.requests_client import OAuth2Session
oauth = load_oauth_client()
client = OAuth2Session(oauth.oauth.client_id, oauth.oauth.client_secret,
Expand Down
7 changes: 0 additions & 7 deletions servicex_app/servicex_app/web/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from flask import current_app
import globus_sdk
from authlib.integrations.flask_client import OAuth

oauth = None
Expand All @@ -19,9 +18,3 @@ def load_oauth_client():
)
oauth.init_app(current_app)
return oauth


def load_app_client():
client_id = current_app.config['OAUTH_CLIENT_ID']
client_secret = current_app.config['OAUTH_CLIENT_SECRET']
return globus_sdk.ConfidentialAppAuthClient(client_id, client_secret)

0 comments on commit 0c46452

Please sign in to comment.