- Notifications
You must be signed in to change notification settings - Fork17
Controls and monitors organization permissions across GitHub, Slack and GSuite. Built with ❤️ by The Electron Team
License
electron/sheriff
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This bot, when deployed as a Heroku app and configured correctly, is capable of controlling permissionsacross GitHub, Slack, Heroku, and GSuite. It also actively monitors and alerts you to suspicious or unexpectedactivity on GitHub.
Using a combination of webhooks and a YAML configuration file, Sheriff will automatically control your permissionsand access controls across GitHub, Slack, Heroku, and GSuite. (Slack and GSuite plugins are optional and disabled by default).
It will post to a designated Slack channel every time it updates any permission setting or any time it detectspotentially suspect actions including new deploy keys with write access, tag deletion or release branch deletion.
If you have an organization with a lot of repositories and/or org members using Sheriff can help ensure your organization remains secure and transparent.
We recommend deploying this as a Heroku app (this is how Electron has deployed it), although you can use anotherdeployment strategy if you want. There are three core components to Sheriff, all of which need to be configuredfor it to work:
Deploy the webhook to Heroku with this button ➡️
To the run the webhook server, you need to start the main Sheriff entry point.
npm start
You then need to create a webhook for your entire organization; you can do this on your organization's GitHub webhooks page:
https://github.com/organizations/{orgname}/settings/hooks/new
You want to specify the following options:
Payload URL- The deployed URL of your webhook server, e.g.https://my-sheriff.mysite.comContent type-application/jsonSecret- Generate a random and secure secret here and save it for later in the configurationWhich events?- Choose "Send me everything"
Finally, click "Add webhook".
To manage GitHub instances, Sheriff requires you to create a GitHub App that gets installed in the desired Org.
The app needs the following OAuth scopes permitted:
Org:administration:writecontents:readmetadata:readRepo:members:writeOnce created, you can generate and download a Private Key for the app, and supply it to Sheriff.
Before setting it asSHERIFF_GITHUB_APP_CREDS, you must pass it through a utility to change the format to what Octokit is expecting:
npx @electron/github-app-auth --creds={path-to-downloaded-private-key} --app-id={id-from-created-github-app}The actual permissions controller should be triggered every 10 minutes as a cron job. You can run this job with:
node lib/permissions/run.js --do-it-for-real-this-time
If you leave off the--do-it-for-real-this-time Sheriff will "dry run" and tell you what itwould have done if you had let it run.
On Heroku you use the "Heroku Scheduler" addon to configure this cron job.
In order to provide realtime information on the actions Sheriff takes, we use a Slack app that sends messages to a channel. You'll need to create your own Slack App by following the instructions below.
- Create a new Slack app onhttps://api.slack.com/apps - Name it whatever you like and choose your workspace as the development workspace
- Go to "Incoming Webhooks" and enable it
- Click "Add New Webhook to Workspace" and choose the channel you want Sheriff to post in to
- Keep a note of the newly created
Webhook URLas you'll need it later for configuration purposes. - Go to "OAuth & Permissions" and add the following OAuth scopes.
usergroups:read,usergroups:write,users:readandusers:read:email. - Follow the prompt to reinstall your app for the new OAuth scopes to take effect
- Keep a note of the
OAuth Access Tokenat the top of the page as you'll need it later for configuration purposes.
The following environment variables represent the configuration of the actual Sheriff deployment. For thepermissions.yaml reference see thePermissions File section.
| Name | Required | Value | For Plugin |
|---|---|---|---|
PERMISSIONS_FILE_ORG | ✔️ | The name of the GitHub org where you put the.permissions repository | |
PERMISSIONS_FILE_REPO | Override the default repo to look forconfig.yaml | .permissions | |
PERMISSIONS_FILE_PATH | Override the default filepath to look for the Sheriff config | config.yaml | |
PERMISSIONS_FILE_REF | Override the default repo branch to look for the Sheriff config | main | |
GITHUB_WEBHOOK_SECRET | ✔️ | The secret for the org-wide webhook you configured earlier | |
SLACK_TOKEN | ✔️ | The token for your Slack App you created earlier | |
SLACK_WEBHOOK_URL | ✔️ | The webhook URL for your Slack App you created earlier | |
SHERIFF_HOST_URL | ✔️ | The fully qualified URL for your deployed webhook | |
SHERIFF_PLUGINS | A comma separated list of plugins to enable. Possible plugins aregsuite andslack | ||
SHERIFF_IMPORTANT_BRANCH | A regular expression to match important branches you want to monitor for deletion | ||
SHERIFF_GITHUB_APP_CREDS | ✔️ | Private key credentials generated for a GitHub App. | |
GSUITE_CREDENTIALS | GSuite credentials | gsuite | |
GSUITE_TOKEN | GSuite authentication token | gsuite | |
SHERIFF_GSUITE_DOMAIN | The primary domain of your GSuite account | gsuiteslack | |
SHERIFF_SLACK_DOMAIN | The "domain" part of{domain}.slack.com for your Slack instance | gsuite if you add slack email addresses to your google groups for notifications |
Your organization permissions are controlled through aconfig.yaml file stored in a.permissions repositoryin your GitHub organization. We keep that.permissions repository private but you can choose to keep itpublic if you wish. That repository needs aconfig.yaml file at the top level that is in the following format:
organization:<name of github org>repository_defaults:# Whether repositories should have wikis enabled by default or not# For security reasons, you should consider defaulting this to falsehas_wiki:<boolean># Teams are not specific to a single platform; they are shared across GitHub, Slack and GSuiteteams: -name:<team name># A list of members / maintainers of this GitHub team# Maintainer in GitHub conveys some extra permissions over the team (set description, avatar, etc.)members: -list -of -gh_usernamesmaintainers: -list -of -gh_usernames# Or don't provide members/maintainers and instead provide a list of other# teams to draw users from. This doesn't set any parent/child relationship# rather it simply says:# for team of formation:# self.members += team.members# self.maintainers += team.maintainers# i.e. doing a union of members/maintainers of the formation teams to create# a new member listformation: -list -of -other -teams# Optional team properties# Human friendly display name for GSuite and Slack groupsdisplayName:<string># Hidden GitHub team? true=yes, false=nosecret:<boolean># Create a slack user group for this team# false=no, true=use name of team, string=custom_name# Used by the `slack` pluginslack:<boolean> | <string># Create a GSuite group for this team# Leave undefined for "no"# Used by the `gsuite` plugingsuite:# internal = only visible to other GSuite members# external = public facing group email addressprivacy:internal | externalrepositories: -name:<repo name>teams:<team_name>:read | triage | write | maintain | adminexternal_collaborators:<gh_username>:read | triage | write | maintain | admin# Optional repository settingssettings:# Wiki enabled? true=yes, false=nohas_wiki:<boolean># Public vs Private repository, no value is assumed to mean publicvisibility:public | privaterulesets: -name-of-common-ruleset# Ruleset names must be unique for a given repository -name:<ruleset name>target:branch | tag# Optional enforcement status, defaults to "active"enforcement:disabled | active | evaluate# Optional bypass configurationbypass:# Team names that can bypass this rulesetteams:Array<string># App ids that can bypass this rulesetapps:Array<number>ref_name:# Targeting ref for this ruleset, "~DEFAULT_BRANCH" is a magic# string that GitHub translates to the current default branchinclude:["~DEFAULT_BRANCH"]# Optional targeting ref for this ruleset that is _excluded_ from the# include matchingexclude:[]# Which basic rules to apply as part of this ruleset# Possible / supported options are included and documented belowrules:# Prevent refs matching this ruleset from being created -restrict_creation# Prevent refs matching this ruleset from being updated -restrict_update# Prevent refs matching this ruleset from being deleted -restrict_deletion# Prevent refs matching this ruleset from receiving force pushes -restrict_force_push# Prevent refs matching this ruleset from receiving merge commits -require_linear_history# Require refs matching this ruleset only receive signed commits -require_signed_commits# Can be simply "true" to require pull requests before changes are pushed to# matching refs. Advanced configuration can be provided via an object as documented# belowrequire_pull_request:# All params are optional and map exactly to the github API# They are also all quite literal :)dismiss_stale_reviews_on_push:<boolean>require_code_owner_review:<boolean>require_last_push_approval:<boolean>required_approving_review_count:<number>required_review_thread_resolution:<boolean># Status checks that are required to make changes to the matching refrequire_status_checks:# The literal check name that is required, this is what shows up in the GitHub UI -context:<string># The app ID that makes this check, this is optional in the GitHub API but required# in sheriff for good security practicesapp_id:<number>common_rulesets:# Same structure as the object in `repositories[name].rulesets`# Used to deduplicate rulesets that you want to apply to multiple repos -<object>
You can generate a permissions file for the current state of your org using thegenerate helper script.
node lib/permissions/generate.js
Please note you may want to edit this generated YAML file:
- All org owners are considered
maintainersof the teams they are in, this may be semantically incorrect - No GSuite or slack configuration is included in the generated file
- You may want to use the
formationproperty to declare larger teams instead of listing all members individually
However in theory running Sheriff immediately on this generated file should result in a no-op run.
You should have alerting set up in case the cron job fails. Occasionally, it willfail due to an unexpected state on GitHub or an incorrect/incomplete permissions file.
- Sheriff is not currently capable of inviting people to your org
- Before adding them to the permissions file, ensure you've added them to the org.
- Sheriff will not remove people from your org, if your has "default member permissions" you should ensure users are manually removed when appropriate
About
Controls and monitors organization permissions across GitHub, Slack and GSuite. Built with ❤️ by The Electron Team
Resources
License
Code of conduct
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors9
Uh oh!
There was an error while loading.Please reload this page.
