Provide finely scoped push access to GitHub from a JupyterHub or HPC system.
These goals are accomplished by:
gh-scoped-creds
) that lets specific users
authorize push access to the selected repositories temporarily - a token
that expires after 8 hours.%ghscopedcreds
) that provides a convenient wrapper to call
gh-scoped-creds
from inside a Jupyter Notebook.In the future, an optional web app might also be provided to aid in authentication.
You can install gh-scoped-creds
from PyPI.
pip install gh-scoped-creds
Create a GitHub app for use by the service (JupyterHub, HPC cluster, etc). You can either create it under your personal account, or preferably under a GitHub organization account (Go to Settings -> Developer Settings -> GitHub Apps -> New GitHub app from the organization's GitHub page).
Give it a descriptive name and description, as your users will see this when they authenticate. Provide a link to a descriptive page explaining your service (if you are using a JupyterHub, this could be just your JupyterHub URL).
Keep the 'Expire user authorization tokens' box checked. The authorisation will expire after 8 hours by default.
Select 'Enable Device Flow', as we rely on the device flow authentication method.
Disable webhooks (uncheck the 'Active' checkbox under 'Webhooks'). All other textboxes can be left empty.
Under 'Repository permissions', select 'Read & write' for 'Contents'. This will provide users authenticating via the app just enough permissions to push and pull from repositories.
Under 'Where can this GitHub App be installed?', select 'Any account'. This will enable users to push to their own user repositories or other organization repositaries, rather than just the repos of the user or organization owning this GitHub app.
Save the Client ID
provided in the information page of the app. You'll need this
in the client. Save the Public link
as well, as users will need to use this to grant
access to particular repositories.
gh-scoped-creds
will need to know the "Client ID" of the created GitHub app to
perform authentication. This can be either set with the environment variable
GH_SCOPED_CREDS_CLIENT_ID
, or be passed in as a commandline parameter --client-id
to
the gh-scoped-creds
script when users use it to authenticate.
Users will need to explicitly grant access to the repos they want to push to from
this particular JupyterHub or HPC system (see Usage section below). Admins can set
the GH_SCOPED_CREDS_APP_URL
environment variable to inform users where to go
to manage this access - gh-scoped-creds
will print this out after authentication.
Users will first need to go to the public page of the GitHub app, and click 'Install App' on their account and in organizations. Clicking 'Install' next to the accounts brings up a page where repository push access can be specified. We highly recommend allowing access only to selected repositories, and explicitly select the repositories this hosted service (JupyterHub, HPC cluster, etc) should be able to push to. You can modify this list afterwards, to make sure you only grant the required permissions.
Given the common usage pattern where you are only pushing to a limited set of repositories from a particular hosted service, this should hopefully not be too cumborsome.
Admins can set the GH_SCOPED_CREDS_APP_URL
to the Public Link of the GitHub
app to make it easier for users to know where to go.
The hosted service must have gh-scoped-creds
installed.
Open a terminal, and type gh-scoped-creds
. If you're in a Python based
Jupyter Notebook, you can also do:
import gh_scoped_creds
%ghscopedcreds
This will offer to open the page in a new window for you, and conveniently copy the code you need to paste in the new window too.
It should give you a link to go to, and a code to input into the web page when that link is opened. Open the link, enter the code there (the page accepts pasting, so you can copy it from the output).
Grant access to the device in the web page, and you're done!
Authentication is valid for 8 hours, and once it expires, this process will need to be repeated. In the future, we might have a web app or other process to make this less painful. However, keeping the length of this session limited drastically helps with security too.
Create an ssh key specifically for the hosted service (JupyterHub, HPC cluster, etc) and add it to your GitHub account. If the key doesn't have a passphrase, this is very insecure - anyone who can exfiltrate your key once can keep it and use it whenever they wish. Even with a passphrase, the key can still be exfiltrated and passphrase stolen when used. There's also no way to restrict which repositories this can push to, which is a big issue.
Create a Personal Access Token and use that. This is a little more insecure than the ssh key, as it can be used to make requests on your behalf too after being stolen! There is also no way to restrict which repositories you can push to.
Create a GitHub deploy key for each repository you want to push to, for each hosted service you want to push from. While this lets you control which repos this ssh key can access, it is still stored long term at risk and can be exfiltrated.