mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
Compare commits
12 Commits
8179eb15c1
...
06810ab8d9
Author | SHA1 | Date | |
---|---|---|---|
|
06810ab8d9 | ||
|
0430e25dcf | ||
|
1dbf60cb43 | ||
|
ccd99b2924 | ||
|
53da2d6b6f | ||
|
31b75891bb | ||
|
d95f0f6eb6 | ||
|
909d48e2de | ||
|
75f6d543bb | ||
|
967ba5432c | ||
|
569d37afe5 | ||
|
c4c189894b |
@@ -11,7 +11,7 @@ response within 24 hours.
|
||||
Please include details on the issue and how you'd like to be credited
|
||||
in our release notes when we publish the fix.
|
||||
|
||||
Our [security model][security-model] document may be a helpful
|
||||
Our [security model][securing-your-zulip-server] document may be a helpful
|
||||
resource.
|
||||
|
||||
## Security announcements
|
||||
@@ -32,6 +32,6 @@ reason to run older major releases.
|
||||
See also our documentation on the [Zulip release
|
||||
lifecycle][release-lifecycle].
|
||||
|
||||
[security-model]: https://zulip.readthedocs.io/en/latest/production/security-model.html
|
||||
[securing-your-zulip-server]: https://zulip.readthedocs.io/en/latest/production/securing-your-zulip-server.html
|
||||
[upgrades]: https://zulip.readthedocs.io/en/stable/production/upgrade.html#upgrading-to-a-release
|
||||
[release-lifecycle]: https://zulip.readthedocs.io/en/latest/overview/release-lifecycle.html
|
||||
|
2
docs/_templates/layout.html
vendored
2
docs/_templates/layout.html
vendored
@@ -6,7 +6,7 @@
|
||||
# version e.g. to say that something is likely to have changed.
|
||||
# For more info see: https://www.sphinx-doc.org/en/master/templating.html
|
||||
#}
|
||||
{% if pagename in ["production/system-configuration", "production/reverse-proxies"] and release.endswith('+git') %}
|
||||
{% if pagename in ["production/securing-your-zulip-server"] and release.endswith('+git') %}
|
||||
{#
|
||||
# This page doesn't exist in the stable documentation yet.
|
||||
# This temporary workaround prevents test failures and should be removed after the next release.
|
||||
|
@@ -60,5 +60,5 @@ Here are the top things to know:
|
||||
to the _index_ (that is _stage_) with `git add`. _Commit_ to the HEAD of the
|
||||
current branch with `git commit`.
|
||||
|
||||
[gitbook-basics]: https://git-scm.com/book/en/v2/Getting-Started-Git-Basics
|
||||
[gitbook-basics]: https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository
|
||||
[understanding-git]: https://web.mit.edu/nelhage/Public/git-slides-2009.pdf
|
||||
|
@@ -443,8 +443,8 @@ complicated rebase.
|
||||
[gitbook-git-pull]: https://git-scm.com/docs/git-pull
|
||||
[gitbook-git-rebase]: https://git-scm.com/docs/git-rebase
|
||||
[gitbook-git-status]: https://git-scm.com/docs/git-status
|
||||
[gitbook-other-envs-bash]: https://git-scm.com/book/en/v2/Git-in-Other-Environments-Git-in-Bash
|
||||
[gitbook-other-envs-zsh]: https://git-scm.com/book/en/v2/Git-in-Other-Environments-Git-in-Zsh
|
||||
[gitbook-other-envs-bash]: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Bash
|
||||
[gitbook-other-envs-zsh]: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh
|
||||
[gitbook-rm]: https://git-scm.com/docs/git-rm
|
||||
[github-help-closing-issues]: https://help.github.com/en/articles/closing-issues-via-commit-messages
|
||||
[github-help-push]: https://help.github.com/en/articles/pushing-to-a-remote
|
||||
|
@@ -52,9 +52,12 @@ chamber with its own users, channels, customizations, and so on. This
|
||||
means that one person might be a user of multiple Zulip realms. The
|
||||
administrators of an organization have a great deal of control over
|
||||
who can register an account, what permissions new users have, etc. For
|
||||
more on security considerations and options, see [the security model
|
||||
section](../production/security-model.md) and the [Zulip help
|
||||
center](https://zulip.com/help/).
|
||||
more on security considerations and options, see our [guide on securing
|
||||
your Zulip server][security-guide], [security overview][security-overview],
|
||||
and the [Zulip help center](https://zulip.com/help/).
|
||||
|
||||
[security-overview]: https://zulip.com/security/
|
||||
[security-guide]: ../production/securing-your-zulip-server.md
|
||||
|
||||
## Components
|
||||
|
||||
|
@@ -1842,8 +1842,8 @@ _Released 2023-05-31_
|
||||
- Removed the `application_server.no_serve_uploads` setting in
|
||||
`/etc/zulip/zulip.conf`, as all uploads requests go through Zulip now.
|
||||
- Installations using the previously undocumented [JWT authentication
|
||||
feature](../production/authentication-methods.md#jwt) will need
|
||||
to make minor adjustments in the format of JWT requests; see the
|
||||
feature](../production/authentication-methods.md#json-web-tokens-jwt) will
|
||||
need to make minor adjustments in the format of JWT requests; see the
|
||||
documentation for details on the new format.
|
||||
- High volume log files like `server.log` are now by default retained
|
||||
for 14 days, configured via the `access_log_retention_days`
|
||||
@@ -1957,8 +1957,8 @@ _Released 2023-01-23_
|
||||
[Rocket.Chat imports](https://zulip.com/help/import-from-rocketchat).
|
||||
- Updated the Intercom integration to return success on `HEAD`
|
||||
requests, which it uses to verify its configuration.
|
||||
- Documented how each
|
||||
[rate limit](../production/security-model.md#rate-limiting)
|
||||
- Documented how each [rate
|
||||
limit](../production/securing-your-zulip-server.md#6-understand-zulips-rate-limiting-system)
|
||||
category is used.
|
||||
- Documented the `reset_authentication_attempt_count` command for when users
|
||||
lock themselves out.
|
||||
|
@@ -47,13 +47,14 @@ When we discover a security issue in Zulip, we publish a security and
|
||||
bug fix release, transparently documenting the issue using the
|
||||
industry-standard [CVE advisory process](https://cve.mitre.org/).
|
||||
|
||||
When new security releases are published, we simultaneously publish
|
||||
the fixes to the `main` and stable release branches, so
|
||||
that anyone using those branches can immediately upgrade as well.
|
||||
When new security releases are published, we simultaneously publish the fixes to
|
||||
the `main` branch and the release branch for the current major release series.
|
||||
|
||||
See also our [security model][security-model] documentation.
|
||||
See also our [security overview][security-overview], and our [guide on securing
|
||||
your Zulip server][securing-your-zulip-server].
|
||||
|
||||
[security-model]: ../production/security-model.md
|
||||
[security-overview]: https://zulip.com/security/
|
||||
[securing-your-zulip-server]: ../production/securing-your-zulip-server.md
|
||||
|
||||
### Git versions
|
||||
|
||||
|
@@ -1,14 +1,34 @@
|
||||
# Authentication methods
|
||||
|
||||
Zulip supports a wide variety of authentication methods. Some of them
|
||||
require configuration to set up.
|
||||
Zulip supports a wide variety of authentication methods:
|
||||
|
||||
- [Email and password](#email-and-password), which is enabled by default.
|
||||
- [Social authentication](#social-authentication) with Google, GitHub,
|
||||
and GitLab, which is easy to set up with a few lines of configuration.
|
||||
Authentication with Apple additionally requires registering with Apple.
|
||||
- [Microsoft Entra ID](#microsoft-entra-id) (AzureAD), which is similarly easy to
|
||||
configure.
|
||||
- [LDAP (including Active Directory)](#ldap-including-active-directory). Zulip
|
||||
supports retrieving information about users via LDAP, and optionally using LDAP
|
||||
as an authentication mechanism.
|
||||
- [SAML](#saml), which is supported by Okta, OneLogin, Entra ID (AzureAD),
|
||||
Keycloak, Auth0 and many other identity providers.
|
||||
- [OpenID Connect](#openid-connect). Zulip can be integrated with any OpenID
|
||||
Connect (OIDC) authentication provider.
|
||||
- [JSON Web Tokens (JWT)](#json-web-tokens-jwt)
|
||||
- [Apache-based SSO with `REMOTE_USER`](#apache-based-sso-with-remote_user)
|
||||
|
||||
To configure or disable authentication methods on your Zulip server,
|
||||
edit the `AUTHENTICATION_BACKENDS` setting in
|
||||
`/etc/zulip/settings.py`, as well as any additional configuration your
|
||||
chosen authentication methods require; then restart the Zulip server.
|
||||
|
||||
Details on each method below.
|
||||
If your authentication provider is not supported out-of-the-box, you can
|
||||
configure [custom authentication backends](#custom-authentication-backends). If
|
||||
you need help, best-effort community support is available in the [Zulip
|
||||
development community](https://zulip.com/development-community/). To inquire
|
||||
about options for custom development, [contact Zulip
|
||||
Sales](mailto:sales@zulip.com).
|
||||
|
||||
## Email and password
|
||||
|
||||
@@ -21,21 +41,124 @@ email and password.
|
||||
When first setting up your Zulip server, this method must be used for
|
||||
creating the initial realm and user. You can disable it after that.
|
||||
|
||||
## Plug-and-play SSO (Google, GitHub, GitLab)
|
||||
### Passwords
|
||||
|
||||
Zulip stores user passwords using the standard Argon2 algorithm.
|
||||
|
||||
When the user is choosing a password, Zulip checks the password's
|
||||
strength using the popular [zxcvbn][zxcvbn] library. Weak passwords
|
||||
are rejected, and strong passwords encouraged. The minimum password
|
||||
strength allowed is controlled by two settings in
|
||||
`/etc/zulip/settings.py`:
|
||||
|
||||
- `PASSWORD_MIN_LENGTH`: The minimum acceptable length, in characters.
|
||||
Shorter passwords are rejected even if they pass the `zxcvbn` test
|
||||
controlled by `PASSWORD_MIN_GUESSES`.
|
||||
|
||||
- `PASSWORD_MIN_GUESSES`: The minimum acceptable strength of the
|
||||
password, in terms of the estimated number of passwords an attacker
|
||||
is likely to guess before trying this one. If the user attempts to
|
||||
set a password that `zxcvbn` estimates to be guessable in less than
|
||||
`PASSWORD_MIN_GUESSES`, then Zulip rejects the password.
|
||||
|
||||
By default, `PASSWORD_MIN_GUESSES` is 10000. This provides
|
||||
significant protection against online attacks, while limiting the
|
||||
burden imposed on users choosing a password. See
|
||||
[password strength](password-strength.md) for an extended
|
||||
discussion on how we chose this value.
|
||||
|
||||
Estimating the guessability of a password is a complex problem and
|
||||
impossible to efficiently do perfectly. For background or when
|
||||
considering an alternate value for this setting, the article
|
||||
["Passwords and the Evolution of Imperfect Authentication"][bhos15]
|
||||
is recommended. The [2016 zxcvbn paper][zxcvbn-paper] adds useful
|
||||
information about the performance of zxcvbn, and [a large 2012 study
|
||||
of Yahoo users][bon12] is informative about the strength of the
|
||||
passwords users choose.
|
||||
|
||||
<!---
|
||||
If the BHOS15 link ever goes dead: it's reference 30 of the zxcvbn
|
||||
paper, aka https://dl.acm.org/citation.cfm?id=2699390 , in the
|
||||
_Communications of the ACM_ aka CACM. (But the ACM has it paywalled.)
|
||||
.
|
||||
Hooray for USENIX and IEEE: the other papers' canonical links are
|
||||
not paywalled. The Yahoo study is reference 5 in BHOS15.
|
||||
-->
|
||||
|
||||
[zxcvbn]: https://github.com/dropbox/zxcvbn
|
||||
[bhos15]: http://www.cl.cam.ac.uk/~fms27/papers/2015-BonneauHerOorSta-passwords.pdf
|
||||
[zxcvbn-paper]: https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_wheeler.pdf
|
||||
[bon12]: http://ieeexplore.ieee.org/document/6234435/
|
||||
|
||||
## Social authentication
|
||||
|
||||
With just a few lines of configuration, your Zulip server can
|
||||
authenticate users with any of several single-sign-on (SSO)
|
||||
authentication providers:
|
||||
authenticate users with:
|
||||
|
||||
- Google accounts, with `GoogleAuthBackend`
|
||||
- GitHub accounts, with `GitHubAuthBackend`
|
||||
- GitLab accounts, with `GitLabAuthBackend`
|
||||
- Microsoft Entra ID (AzureAD), with `AzureADAuthBackend`
|
||||
|
||||
Each of these requires one to a handful of lines of configuration in
|
||||
`settings.py`, as well as a secret in `zulip-secrets.conf`. Details
|
||||
are documented in your `settings.py`.
|
||||
|
||||
### Sign in with Apple
|
||||
|
||||
Zulip supports using the web flow for Sign in with Apple on
|
||||
self-hosted servers. To do so, you'll need to do the following:
|
||||
|
||||
1. Visit [the Apple Developer site][apple-developer] and [Create a
|
||||
Services ID][apple-create-services-id]. When prompted for a "Return
|
||||
URL", enter `https://zulip.example.com/complete/apple/` (using the
|
||||
domain for your server).
|
||||
|
||||
1. Create a [Sign in with Apple private key][apple-create-private-key].
|
||||
|
||||
1. Store the resulting private key at
|
||||
`/etc/zulip/apple-auth-key.p8`. Be sure to set
|
||||
permissions correctly:
|
||||
|
||||
```bash
|
||||
chown zulip:zulip /etc/zulip/apple-auth-key.p8
|
||||
chmod 640 /etc/zulip/apple-auth-key.p8
|
||||
```
|
||||
|
||||
1. Configure Apple authentication in `/etc/zulip/settings.py`:
|
||||
|
||||
- `SOCIAL_AUTH_APPLE_TEAM`: Your Team ID from Apple, which is a
|
||||
string like "A1B2C3D4E5".
|
||||
- `SOCIAL_AUTH_APPLE_SERVICES_ID`: The Services ID you created in
|
||||
step 1, which might look like "com.example.services".
|
||||
- `SOCIAL_AUTH_APPLE_APP_ID`: The App ID, or Bundle ID, of your
|
||||
app that you used in step 1 to configure your Services ID.
|
||||
This might look like "com.example.app".
|
||||
- `SOCIAL_AUTH_APPLE_KEY`: Despite the name this is not a key, but
|
||||
rather the Key ID of the key you created in step 2. This looks
|
||||
like "F6G7H8I9J0".
|
||||
- `AUTHENTICATION_BACKENDS`: Uncomment (or add) a line like
|
||||
`'zproject.backends.AppleAuthBackend',` to enable Apple auth
|
||||
using the created configuration.
|
||||
|
||||
1. Register with Apple the email addresses or domains your Zulip
|
||||
server sends email to users from. For instructions and background,
|
||||
see the "Email Relay Service" subsection of
|
||||
[this page][apple-get-started]. For details on what email
|
||||
addresses Zulip sends from, see our
|
||||
[outgoing email documentation][outgoing-email].
|
||||
|
||||
[apple-create-services-id]: https://help.apple.com/developer-account/?lang=en#/dev1c0e25352
|
||||
[apple-developer]: https://developer.apple.com/account/resources/
|
||||
[apple-create-private-key]: https://help.apple.com/developer-account/?lang=en#/dev77c875b7e
|
||||
[apple-get-started]: https://developer.apple.com/sign-in-with-apple/get-started/
|
||||
[outgoing-email]: email.md
|
||||
|
||||
## Microsoft Entra ID
|
||||
|
||||
Set up authentication with Microsoft Entra ID (AzureAD) by modifying the
|
||||
`AzureADAuthBackend` configuration in `settings.py`, as well as a secret in
|
||||
`zulip-secrets.conf`. Details are documented in your `settings.py`.
|
||||
|
||||
(ldap)=
|
||||
|
||||
## LDAP (including Active Directory)
|
||||
@@ -45,10 +168,10 @@ optionally using LDAP as an authentication mechanism.
|
||||
|
||||
In either configuration, you will need to do the following:
|
||||
|
||||
1. These instructions assume you have an installed Zulip server and
|
||||
are logged into a shell there. You can have created an
|
||||
organization already using EmailAuthBackend, or plan to create the
|
||||
organization using LDAP authentication.
|
||||
1. [Install a Zulip server](./install.md), and log into a shell.
|
||||
|
||||
1. _(optional)_ Create an organization using EmailAuthBackend. Alternately, you
|
||||
can plan to create the organization using LDAP authentication.
|
||||
|
||||
1. Tell Zulip how to connect to your LDAP server:
|
||||
|
||||
@@ -815,7 +938,7 @@ integration](../production/scim.md).
|
||||
|
||||
### Using Authentik as a SAML IdP
|
||||
|
||||
1. Make sure you reviewed [this article](https://goauthentik.io/integrations/services/zulip/), which
|
||||
1. Make sure you reviewed [this article](https://integrations.goauthentik.io/chat-communication-collaboration/zulip/), which
|
||||
details how to integrate Zulip with Authentik.
|
||||
1. Verify that `SOCIAL_AUTH_SAML_ENABLED_IDPS[{idp_name}]['entity_id']` and
|
||||
`SOCIAL_AUTH_SAML_ENABLED_IDPS[{idp_name}]['url']` are correct in your Zulip
|
||||
@@ -1040,56 +1163,6 @@ to debug.
|
||||
sees the cookie, treats them as logged in, and proceeds to serve
|
||||
them the main app page normally.
|
||||
|
||||
## Sign in with Apple
|
||||
|
||||
Zulip supports using the web flow for Sign in with Apple on
|
||||
self-hosted servers. To do so, you'll need to do the following:
|
||||
|
||||
1. Visit [the Apple Developer site][apple-developer] and [Create a
|
||||
Services ID.][apple-create-services-id]. When prompted for a "Return
|
||||
URL", enter `https://zulip.example.com/complete/apple/` (using the
|
||||
domain for your server).
|
||||
|
||||
1. Create a [Sign in with Apple private key][apple-create-private-key].
|
||||
|
||||
1. Store the resulting private key at
|
||||
`/etc/zulip/apple-auth-key.p8`. Be sure to set
|
||||
permissions correctly:
|
||||
|
||||
```bash
|
||||
chown zulip:zulip /etc/zulip/apple-auth-key.p8
|
||||
chmod 640 /etc/zulip/apple-auth-key.p8
|
||||
```
|
||||
|
||||
1. Configure Apple authentication in `/etc/zulip/settings.py`:
|
||||
|
||||
- `SOCIAL_AUTH_APPLE_TEAM`: Your Team ID from Apple, which is a
|
||||
string like "A1B2C3D4E5".
|
||||
- `SOCIAL_AUTH_APPLE_SERVICES_ID`: The Services ID you created in
|
||||
step 1, which might look like "com.example.services".
|
||||
- `SOCIAL_AUTH_APPLE_APP_ID`: The App ID, or Bundle ID, of your
|
||||
app that you used in step 1 to configure your Services ID.
|
||||
This might look like "com.example.app".
|
||||
- `SOCIAL_AUTH_APPLE_KEY`: Despite the name this is not a key, but
|
||||
rather the Key ID of the key you created in step 2. This looks
|
||||
like "F6G7H8I9J0".
|
||||
- `AUTHENTICATION_BACKENDS`: Uncomment (or add) a line like
|
||||
`'zproject.backends.AppleAuthBackend',` to enable Apple auth
|
||||
using the created configuration.
|
||||
|
||||
1. Register with Apple the email addresses or domains your Zulip
|
||||
server sends email to users from. For instructions and background,
|
||||
see the "Email Relay Service" subsection of
|
||||
[this page][apple-get-started]. For details on what email
|
||||
addresses Zulip sends from, see our
|
||||
[outgoing email documentation][outgoing-email].
|
||||
|
||||
[apple-create-services-id]: https://help.apple.com/developer-account/?lang=en#/dev1c0e25352
|
||||
[apple-developer]: https://developer.apple.com/account/resources/
|
||||
[apple-create-private-key]: https://help.apple.com/developer-account/?lang=en#/dev77c875b7e
|
||||
[apple-get-started]: https://developer.apple.com/sign-in-with-apple/get-started/
|
||||
[outgoing-email]: email.md
|
||||
|
||||
## OpenID Connect
|
||||
|
||||
Zulip can be integrated with any OpenID Connect (OIDC) authentication
|
||||
@@ -1123,7 +1196,7 @@ assumes the name is correct, and new users will not be presented with
|
||||
a registration form unless they need to accept Terms of Service for
|
||||
the server (i.e. `TERMS_OF_SERVICE_VERSION` is set).
|
||||
|
||||
## JWT
|
||||
## JSON Web Tokens (JWT)
|
||||
|
||||
Zulip supports using JSON Web Tokens (JWT) authentication in two ways:
|
||||
|
||||
@@ -1146,7 +1219,9 @@ configure the JWT secret and algorithm via `JWT_AUTH_KEYS` in
|
||||
`/etc/zulip/settings.py`; see the inline comment documentation in that
|
||||
file for details.
|
||||
|
||||
## Configuring a custom Python wrapper around the `authenticate` mechanism
|
||||
## Custom authentication backends
|
||||
|
||||
### Configuring a custom Python wrapper around the `authenticate` mechanism
|
||||
|
||||
Zulip supports configuring a custom authentication function that will
|
||||
work as a wrapper around every login attempt to Zulip, enabling custom
|
||||
@@ -1239,11 +1314,11 @@ request), this is where it should happen.
|
||||
|
||||
[django-authenticate-details]: https://docs.djangoproject.com/en/5.0/topics/auth/customizing/#writing-an-authentication-backend
|
||||
|
||||
## Adding more authentication backends
|
||||
### Adding more authentication backends
|
||||
|
||||
Adding an integration with any of the more than 100 authentication
|
||||
providers supported by [python-social-auth][python-social-auth] (e.g.,
|
||||
Facebook, Twitter, etc.) is easy to do if you're willing to write a
|
||||
Facebook, X, etc.) is easy to do if you're willing to write a
|
||||
bit of code, and pull requests to add new backends are welcome.
|
||||
|
||||
For example, the
|
||||
|
@@ -49,10 +49,10 @@ email addresses and send notifications.
|
||||
|
||||
For sending outgoing email from your Zulip server, we highly recommend
|
||||
using a "transactional email" service like
|
||||
[Mailgun](https://documentation.mailgun.com/en/latest/quickstart-sending.html#send-via-smtp),
|
||||
[SendGrid](https://sendgrid.com/docs/API_Reference/SMTP_API/integrating_with_the_smtp_api.html),
|
||||
[Mailgun](https://documentation.mailgun.com/docs/mailgun/user-manual/sending-messages/send-smtp),
|
||||
[SendGrid](https://www.twilio.com/docs/sendgrid/for-developers/sending-email/integrating-with-the-smtp-api),
|
||||
or, for AWS users,
|
||||
[Amazon SES](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-smtp.html).
|
||||
[Amazon SES](https://docs.aws.amazon.com/ses/latest/dg/send-email-smtp.html).
|
||||
These services are designed to send email from servers, and are by far
|
||||
the easiest way to get outgoing email working reliably (Mailgun has
|
||||
the best documentation).
|
||||
|
@@ -14,7 +14,7 @@ system-configuration
|
||||
mobile-push-notifications
|
||||
upgrade
|
||||
modify
|
||||
security-model
|
||||
securing-your-zulip-server
|
||||
authentication-methods
|
||||
export-and-import
|
||||
postgresql
|
||||
|
@@ -192,7 +192,8 @@ Learning more:
|
||||
server administrators. This extremely low-traffic list is for
|
||||
important announcements, including [new
|
||||
releases](../overview/release-lifecycle.md) and security issues.
|
||||
- Follow [Zulip on Twitter](https://twitter.com/zulip).
|
||||
- Follow us on [Mastodon](https://fosstodon.org/@zulip) or
|
||||
[X/Twitter](https://x.com/zulip).
|
||||
- Learn how to [configure your Zulip server settings](settings.md).
|
||||
- Learn about [Backups, export and import](export-and-import.md)
|
||||
and [upgrading](upgrade.md) a production Zulip
|
||||
|
@@ -13,7 +13,7 @@ Moved to [Troubleshooting](troubleshooting.md#monitoring).
|
||||
|
||||
### Securing your Zulip server
|
||||
|
||||
Moved to [Security model](security-model.md).
|
||||
Moved to [Securing your Zulip server](securing-your-zulip-server.md).
|
||||
|
||||
### Upgrading
|
||||
|
||||
|
@@ -8,8 +8,8 @@ When a user tries to set a password, we use [zxcvbn][zxcvbn] to check
|
||||
that it isn't a weak one.
|
||||
|
||||
See discussion in [our main docs for server
|
||||
admins](security-model.md#passwords). This doc explains in more
|
||||
detail how we set the default threshold (`PASSWORD_MIN_GUESSES`) we use.
|
||||
admins](authentication-methods.md#email-and-password). This doc explains in
|
||||
more detail how we set the default threshold (`PASSWORD_MIN_GUESSES`) we use.
|
||||
|
||||
First, read the doc section there. (It's short.)
|
||||
|
||||
|
160
docs/production/securing-your-zulip-server.md
Normal file
160
docs/production/securing-your-zulip-server.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# Securing your Zulip server
|
||||
|
||||
This page offers practical information on how to secure your Zulip server. For a
|
||||
deeper understanding of the security model, take a look at Zulip's [security
|
||||
overview](https://zulip.com/security/).
|
||||
|
||||
Here are some best practices for keeping your Zulip server secure:
|
||||
|
||||
1. [Limit shell access to a small set of trusted individuals.](#1-limit-shell-access-to-a-small-set-of-trusted-individuals)
|
||||
2. [Consider requiring authentication with single sign-on (SSO).](#2-consider-requiring-authentication-with-single-sign-on-sso)
|
||||
3. [Teach users how to protect their account.](#3-teach-users-how-to-protect-their-account)
|
||||
4. [Become familiar with Zulip's access management model.](#4-become-familiar-with-zulips-access-management-model)
|
||||
5. [Understand security for user-uploaded content and user-generated requests.](#5-understand-security-for-user-uploaded-content-and-user-generated-requests)
|
||||
6. [Understand Zulip's rate-limiting system.](#6-understand-zulips-rate-limiting-system)
|
||||
|
||||
If you believe you've identified a security issue, please report it to Zulip's
|
||||
security team at [security@zulip.com](mailto:security@zulip.com) as soon as
|
||||
possible, so that we can address it and make a responsible disclosure.
|
||||
|
||||
## 1. Limit shell access to a small set of trusted individuals.
|
||||
|
||||
Anyone with root access to a Zulip application server or Zulip database server,
|
||||
or with access to the `zulip` user on a Zulip application server, has _complete
|
||||
control over the Zulip installation_ and all of its data (so they can read
|
||||
messages, modify history, etc.). This means that _only trusted individuals_
|
||||
should have shell access to your Zulip server.
|
||||
|
||||
## 2. Consider requiring authentication with single sign-on (SSO).
|
||||
|
||||
The preferred way to log in to Zulip is using a single sign-on (SSO)
|
||||
solution like Google authentication, LDAP, or similar, but Zulip
|
||||
also supports password authentication. See [the authentication
|
||||
methods documentation](authentication-methods.md) for
|
||||
details on Zulip's available authentication methods.
|
||||
|
||||
## 3. Teach users how to protect their account.
|
||||
|
||||
Every Zulip user has an API key, which can be used to do essentially everything
|
||||
that users can do when they're logged in. Make sure users know to immediately
|
||||
[reset their API key and password](https://zulip.com/help/protect-your-account)
|
||||
if their credentials are compromised (e.g., their cell phone is lost or stolen).
|
||||
|
||||
## 4. Become familiar with Zulip's access management model.
|
||||
|
||||
Zulip's help center offers a detailed overview of Zulip's permissions management
|
||||
system. Reading the following guides will give you a good starting point:
|
||||
|
||||
- [Channel types and permissions](https://zulip.com/help/channel-permissions)
|
||||
- [User roles](https://zulip.com/help/user-roles)
|
||||
- [User groups](https://zulip.com/help/user-groups)
|
||||
- [Restrict message editing and deletion](https://zulip.com/help/restrict-message-editing-and-deletion)
|
||||
- [Bots overview](https://zulip.com/help/bots-overview)
|
||||
|
||||
## 5. Understand security for user-uploaded content and user-generated requests.
|
||||
|
||||
- Zulip supports user-uploaded files. Ideally they should be hosted
|
||||
from a separate domain from the main Zulip server to protect against
|
||||
various same-domain attacks (e.g., zulip-user-content.example.com).
|
||||
|
||||
We support two ways of hosting them: the basic `LOCAL_UPLOADS_DIR`
|
||||
file storage backend, where they are stored in a directory on the
|
||||
Zulip server's filesystem, and the S3 backend, where the files are
|
||||
stored in Amazon S3. It would not be difficult to add additional
|
||||
supported backends should there be a need; see
|
||||
`zerver/lib/upload.py` for the full interface.
|
||||
|
||||
For both backends, the URLs used to access uploaded files are long,
|
||||
random strings, providing one layer of security against unauthorized
|
||||
users accessing files uploaded in Zulip (an authorized user would
|
||||
need to share the URL with an unauthorized user in order for the
|
||||
file to be accessed by the unauthorized user. Of course, any
|
||||
such authorized user could have just downloaded and sent the file
|
||||
instead of the URL, so this is arguably pretty good protection.)
|
||||
|
||||
However, to help protect against accidental sharing of URLs to
|
||||
restricted files (e.g., by forwarding a missed-message email or leaks
|
||||
involving the Referer header), every access to an uploaded file has
|
||||
access control verified (confirming that the browser is logged into
|
||||
a Zulip account that has received the uploaded file in question).
|
||||
|
||||
- Zulip supports using the [go-camo][go-camo] image proxy to proxy content like
|
||||
inline image previews, that can be inserted into the Zulip message feed by
|
||||
other users. This ensures that clients do not make requests to external
|
||||
servers to fetch images, improving privacy.
|
||||
|
||||
- By default, Zulip will provide image previews inline in the body of
|
||||
messages when a message contains a link to an image. You can
|
||||
control this using the `INLINE_IMAGE_PREVIEW` setting.
|
||||
|
||||
- Zulip may make outgoing HTTP connections to other servers in a
|
||||
number of cases:
|
||||
|
||||
- Outgoing webhook bots (creation of which can be restricted)
|
||||
- Inline image previews in messages (enabled by default, but can be disabled)
|
||||
- Inline webpage previews and embeds (must be configured to be enabled)
|
||||
- Twitter message previews (must be configured to be enabled)
|
||||
- BigBlueButton and Zoom API requests (must be configured to be enabled)
|
||||
- Mobile push notifications (must be configured to be enabled)
|
||||
|
||||
- Notably, these first 3 features give end users (limited) control to cause
|
||||
the Zulip server to make HTTP requests on their behalf. Because of this,
|
||||
Zulip routes all outgoing HTTP requests [through
|
||||
Smokescreen][smokescreen-setup] to ensure that Zulip cannot be
|
||||
used to execute [SSRF attacks][ssrf] against other systems on an
|
||||
internal corporate network. The default Smokescreen configuration
|
||||
denies access to all non-public IP addresses, including 127.0.0.1.
|
||||
|
||||
The Camo image server does not, by default, route its traffic
|
||||
through Smokescreen, since Camo includes logic to deny access to
|
||||
private subnets; this can be [overridden][proxy.enable_for_camo].
|
||||
|
||||
[go-camo]: https://github.com/cactus/go-camo
|
||||
[ssrf]: https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
|
||||
[smokescreen-setup]: deployment.md#customizing-the-outgoing-http-proxy
|
||||
[proxy.enable_for_camo]: system-configuration.md#enable_for_camo
|
||||
|
||||
## 6. Understand Zulip's rate-limiting system.
|
||||
|
||||
Zulip has built-in rate limiting of login attempts, all access to the
|
||||
API, as well as certain other types of actions that may be involved in
|
||||
abuse. For example, the email confirmation flow, by its nature, needs
|
||||
to allow sending an email to an email address that isn't associated
|
||||
with an existing Zulip account. Limiting the ability of users to
|
||||
trigger such emails helps prevent bad actors from damaging the spam
|
||||
reputation of a Zulip server by sending confirmation emails to random
|
||||
email addresses.
|
||||
|
||||
The default rate limiting rules for a Zulip server will change as we improve
|
||||
the product. A server administrator can browse the current rules using
|
||||
`/home/zulip/deployments/current/scripts/get-django-setting
|
||||
RATE_LIMITING_RULES`; or with comments by reading
|
||||
`DEFAULT_RATE_LIMITING_RULES` in `zproject/default_settings.py`.
|
||||
|
||||
Server administrators can tweak rate limiting in the following ways in
|
||||
`/etc/zulip/settings.py`:
|
||||
|
||||
- The `RATE_LIMITING` setting can be set to `False` to completely
|
||||
disable all rate-limiting.
|
||||
- The `RATE_LIMITING_RULES` setting can be used to override specific
|
||||
rules. See the comment in the file for more specific details on how
|
||||
to do it. After changing the setting, we recommend using
|
||||
`/home/zulip/deployments/current/scripts/get-django-setting
|
||||
RATE_LIMITING_RULES` to verify your changes. You can then restart
|
||||
the Zulip server with `scripts/restart-server` to have the new
|
||||
configuration take effect.
|
||||
- The `RATE_LIMIT_TOR_TOGETHER` setting can be set to `True` to group all
|
||||
known exit nodes of [TOR](https://www.torproject.org/) together for purposes
|
||||
of IP address limiting. Since traffic from a client using TOR is distributed
|
||||
across its exit nodes, without enabling this setting, TOR can otherwise be
|
||||
used to avoid IP-based rate limiting. The updated list of TOR exit nodes
|
||||
is refetched once an hour.
|
||||
- If a user runs into the rate limit for login attempts, a server
|
||||
administrator can clear this state using the
|
||||
`manage.py reset_authentication_attempt_count`
|
||||
[management command][management-commands].
|
||||
|
||||
See also our [API documentation on rate limiting][rate-limit-api].
|
||||
|
||||
[management-commands]: ../production/management-commands.md
|
||||
[rate-limit-api]: https://zulip.com/api/rest-error-handling#rate-limit-exceeded
|
@@ -1,320 +0,0 @@
|
||||
# Security model
|
||||
|
||||
This section attempts to document the Zulip security model. It likely
|
||||
does not cover every issue; if there are details you're curious about,
|
||||
please feel free to ask questions in [#production
|
||||
help](https://chat.zulip.org/#narrow/channel/31-production-help) on the
|
||||
[Zulip community server](https://zulip.com/development-community/) (or if you
|
||||
think you've found a security bug, please report it to
|
||||
security@zulip.com so we can do a responsible security
|
||||
announcement).
|
||||
|
||||
## Secure your Zulip server like your email server
|
||||
|
||||
- It's reasonable to think about security for a Zulip server like you
|
||||
do security for a team email server -- only trusted individuals
|
||||
within an organization should have shell access to the server.
|
||||
|
||||
In particular, anyone with root access to a Zulip application server
|
||||
or Zulip database server, or with access to the `zulip` user on a
|
||||
Zulip application server, has complete control over the Zulip
|
||||
installation and all of its data (so they can read messages, modify
|
||||
history, etc.). It would be difficult or impossible to avoid this,
|
||||
because the server needs access to the data to support features
|
||||
expected of a group chat system like the ability to search the
|
||||
entire message history, and thus someone with control over the
|
||||
server has access to that data as well.
|
||||
|
||||
## Encryption and authentication
|
||||
|
||||
- Traffic between clients (web, desktop and mobile) and the Zulip
|
||||
server is encrypted using HTTPS. By default, all Zulip services
|
||||
talk to each other either via a localhost connection or using an
|
||||
encrypted SSL connection.
|
||||
|
||||
- Zulip requires CSRF tokens in all interactions with the web API to
|
||||
prevent CSRF attacks.
|
||||
|
||||
- The preferred way to log in to Zulip is using a single sign-on (SSO)
|
||||
solution like Google authentication, LDAP, or similar, but Zulip
|
||||
also supports password authentication. See [the authentication
|
||||
methods documentation](authentication-methods.md) for
|
||||
details on Zulip's available authentication methods.
|
||||
|
||||
### Passwords
|
||||
|
||||
Zulip stores user passwords using the standard Argon2 and PBKDF2
|
||||
algorithms. Argon2 is used for all new and changed passwords as of
|
||||
Zulip Server 1.6.0, but legacy PBKDF2 passwords that were last changed
|
||||
before the 1.6.0 upgrade are still supported.
|
||||
|
||||
When the user is choosing a password, Zulip checks the password's
|
||||
strength using the popular [zxcvbn][zxcvbn] library. Weak passwords
|
||||
are rejected, and strong passwords encouraged. The minimum password
|
||||
strength allowed is controlled by two settings in
|
||||
`/etc/zulip/settings.py`:
|
||||
|
||||
- `PASSWORD_MIN_LENGTH`: The minimum acceptable length, in characters.
|
||||
Shorter passwords are rejected even if they pass the `zxcvbn` test
|
||||
controlled by `PASSWORD_MIN_GUESSES`.
|
||||
|
||||
- `PASSWORD_MIN_GUESSES`: The minimum acceptable strength of the
|
||||
password, in terms of the estimated number of passwords an attacker
|
||||
is likely to guess before trying this one. If the user attempts to
|
||||
set a password that `zxcvbn` estimates to be guessable in less than
|
||||
`PASSWORD_MIN_GUESSES`, then Zulip rejects the password.
|
||||
|
||||
By default, `PASSWORD_MIN_GUESSES` is 10000. This provides
|
||||
significant protection against online attacks, while limiting the
|
||||
burden imposed on users choosing a password. See
|
||||
[password strength](password-strength.md) for an extended
|
||||
discussion on how we chose this value.
|
||||
|
||||
Estimating the guessability of a password is a complex problem and
|
||||
impossible to efficiently do perfectly. For background or when
|
||||
considering an alternate value for this setting, the article
|
||||
["Passwords and the Evolution of Imperfect Authentication"][bhos15]
|
||||
is recommended. The [2016 zxcvbn paper][zxcvbn-paper] adds useful
|
||||
information about the performance of zxcvbn, and [a large 2012 study
|
||||
of Yahoo users][bon12] is informative about the strength of the
|
||||
passwords users choose.
|
||||
|
||||
<!---
|
||||
If the BHOS15 link ever goes dead: it's reference 30 of the zxcvbn
|
||||
paper, aka https://dl.acm.org/citation.cfm?id=2699390 , in the
|
||||
_Communications of the ACM_ aka CACM. (But the ACM has it paywalled.)
|
||||
.
|
||||
Hooray for USENIX and IEEE: the other papers' canonical links are
|
||||
not paywalled. The Yahoo study is reference 5 in BHOS15.
|
||||
-->
|
||||
|
||||
[zxcvbn]: https://github.com/dropbox/zxcvbn
|
||||
[bhos15]: http://www.cl.cam.ac.uk/~fms27/papers/2015-BonneauHerOorSta-passwords.pdf
|
||||
[zxcvbn-paper]: https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_wheeler.pdf
|
||||
[bon12]: http://ieeexplore.ieee.org/document/6234435/
|
||||
|
||||
## Messages and history
|
||||
|
||||
- Zulip message content is rendered using a specialized Markdown
|
||||
parser which escapes content to protect against cross-site scripting
|
||||
attacks.
|
||||
|
||||
- Zulip supports both public channels and private channels.
|
||||
|
||||
- Any non-guest user can join any public channel in the organization,
|
||||
and can view the complete message history of any public channel
|
||||
without joining the channel. Guests can only access channels that
|
||||
another user adds them to.
|
||||
|
||||
- Organization owners and administrators can see and modify most
|
||||
aspects of a private channel, including the membership and
|
||||
estimated traffic. Owners and administrators generally cannot see
|
||||
messages sent to private channels or do things that would
|
||||
indirectly give them access to those messages, like adding members
|
||||
or changing the channel privacy settings.
|
||||
|
||||
- Non-admins cannot easily see which private channels exist, or interact
|
||||
with them in any way until they are added. Given a channel name, they can
|
||||
figure out whether a channel with that name exists, but cannot see any
|
||||
other details about the channel.
|
||||
|
||||
- See [channel types and permissions](https://zulip.com/help/channel-permissions)
|
||||
for more details.
|
||||
|
||||
- Zulip supports editing the content and topics of messages that have
|
||||
already been sent. As a general philosophy, our policies provide
|
||||
hard limits on the ways in which message content can be changed or
|
||||
undone. In contrast, our policies around message topics favor
|
||||
usefulness (e.g., for conversational organization) over faithfulness
|
||||
to the original. In all configurations:
|
||||
|
||||
- Message content can only ever be modified by the original author.
|
||||
|
||||
- Organization administrators can configure who has permission to
|
||||
delete their own message, and who can delete other users'
|
||||
messages that they can see.
|
||||
|
||||
- See
|
||||
[Restrict message editing and deletion](https://zulip.com/help/restrict-message-editing-and-deletion)
|
||||
for more details.
|
||||
|
||||
## Users and bots
|
||||
|
||||
- There are several types of users in a Zulip organization: organization
|
||||
owners, organization administrators, members (normal users), guests,
|
||||
and bots.
|
||||
|
||||
- Owners and administrators have the ability to deactivate and
|
||||
reactivate other human and bot users, archive channels, add/remove
|
||||
administrator privileges, as well as change configuration for the
|
||||
organization.
|
||||
|
||||
Being an organization administrator does not generally provide the ability
|
||||
to read other users' direct messages or messages sent to private
|
||||
channels to which the administrator is not subscribed. There are two
|
||||
exceptions:
|
||||
|
||||
- Organization owners may get access to direct messages via some types of
|
||||
[data export](https://zulip.com/help/export-your-organization).
|
||||
|
||||
- Administrators can change the ownership of a bot. If a bot is subscribed
|
||||
to a private channel, then an administrator can indirectly get access to
|
||||
channel messages by taking control of the bot, though the access will be
|
||||
limited to what the bot can do. (e.g., incoming webhook bots cannot read
|
||||
messages.)
|
||||
|
||||
- Every Zulip user has an API key, available on the settings page.
|
||||
This API key can be used to do essentially everything the user can
|
||||
do; for that reason, users should keep their API key safe. Users
|
||||
can rotate their own API key if it is accidentally compromised.
|
||||
|
||||
- To properly remove a user's access to a Zulip team, it does not
|
||||
suffice to change their password or deactivate their account in a
|
||||
single sign-on (SSO) system, since neither of those prevents
|
||||
authenticating with the user's API key or those of bots the user has
|
||||
created. Instead, you should [deactivate the user's
|
||||
account](https://zulip.com/help/deactivate-or-reactivate-a-user) via
|
||||
Zulip's "Organization settings" interface.
|
||||
|
||||
- The Zulip mobile apps authenticate to the server by sending the
|
||||
user's password and retrieving the user's API key; the apps then use
|
||||
the API key to authenticate all future interactions with the site.
|
||||
Thus, if a user's phone is lost, in addition to changing passwords,
|
||||
you should rotate the user's Zulip API key.
|
||||
|
||||
- Guest users are like Members, but they do not have automatic access
|
||||
to public channels.
|
||||
|
||||
- Zulip supports several kinds of bots with different capabilities.
|
||||
|
||||
- Incoming webhook bots can only send messages into Zulip.
|
||||
- Outgoing webhook bots and Generic bots can essentially do anything a
|
||||
non-administrator user can, with a few exceptions (e.g., a bot cannot
|
||||
log in to the web application, register for mobile push
|
||||
notifications, or create other bots).
|
||||
- Bots with the `can_forge_sender` permission can send messages that appear to have been sent by
|
||||
another user. They also have the ability to see the names of all
|
||||
channels, including private channels. This is important for implementing
|
||||
integrations like the Jabber, IRC, and Zephyr mirrors.
|
||||
|
||||
These bots cannot be created by Zulip users, including
|
||||
organization owners. They can only be created on the command
|
||||
line (via `manage.py change_user_role can_forge_sender`).
|
||||
|
||||
## User-uploaded content and user-generated requests
|
||||
|
||||
- Zulip supports user-uploaded files. Ideally they should be hosted
|
||||
from a separate domain from the main Zulip server to protect against
|
||||
various same-domain attacks (e.g., zulip-user-content.example.com).
|
||||
|
||||
We support two ways of hosting them: the basic `LOCAL_UPLOADS_DIR`
|
||||
file storage backend, where they are stored in a directory on the
|
||||
Zulip server's filesystem, and the S3 backend, where the files are
|
||||
stored in Amazon S3. It would not be difficult to add additional
|
||||
supported backends should there be a need; see
|
||||
`zerver/lib/upload.py` for the full interface.
|
||||
|
||||
For both backends, the URLs used to access uploaded files are long,
|
||||
random strings, providing one layer of security against unauthorized
|
||||
users accessing files uploaded in Zulip (an authorized user would
|
||||
need to share the URL with an unauthorized user in order for the
|
||||
file to be accessed by the unauthorized user. Of course, any
|
||||
such authorized user could have just downloaded and sent the file
|
||||
instead of the URL, so this is arguably pretty good protection.)
|
||||
|
||||
However, to help protect against accidental sharing of URLs to
|
||||
restricted files (e.g., by forwarding a missed-message email or leaks
|
||||
involving the Referer header), every access to an uploaded file has
|
||||
access control verified (confirming that the browser is logged into
|
||||
a Zulip account that has received the uploaded file in question).
|
||||
|
||||
- Zulip supports using the [go-camo][go-camo] image proxy to proxy content like
|
||||
inline image previews, that can be inserted into the Zulip message feed by
|
||||
other users. This ensures that clients do not make requests to external
|
||||
servers to fetch images, improving privacy.
|
||||
|
||||
- By default, Zulip will provide image previews inline in the body of
|
||||
messages when a message contains a link to an image. You can
|
||||
control this using the `INLINE_IMAGE_PREVIEW` setting.
|
||||
|
||||
- Zulip may make outgoing HTTP connections to other servers in a
|
||||
number of cases:
|
||||
|
||||
- Outgoing webhook bots (creation of which can be restricted)
|
||||
- Inline image previews in messages (enabled by default, but can be disabled)
|
||||
- Inline webpage previews and embeds (must be configured to be enabled)
|
||||
- Twitter message previews (must be configured to be enabled)
|
||||
- BigBlueButton and Zoom API requests (must be configured to be enabled)
|
||||
- Mobile push notifications (must be configured to be enabled)
|
||||
|
||||
- Notably, these first 3 features give end users (limited) control to cause
|
||||
the Zulip server to make HTTP requests on their behalf. Because of this,
|
||||
Zulip routes all outgoing HTTP requests [through
|
||||
Smokescreen][smokescreen-setup] to ensure that Zulip cannot be
|
||||
used to execute [SSRF attacks][ssrf] against other systems on an
|
||||
internal corporate network. The default Smokescreen configuration
|
||||
denies access to all non-public IP addresses, including 127.0.0.1.
|
||||
|
||||
The Camo image server does not, by default, route its traffic
|
||||
through Smokescreen, since Camo includes logic to deny access to
|
||||
private subnets; this can be [overridden][proxy.enable_for_camo].
|
||||
|
||||
[go-camo]: https://github.com/cactus/go-camo
|
||||
[ssrf]: https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
|
||||
[smokescreen-setup]: deployment.md#customizing-the-outgoing-http-proxy
|
||||
[proxy.enable_for_camo]: system-configuration.md#enable_for_camo
|
||||
|
||||
## Rate limiting
|
||||
|
||||
Zulip has built-in rate limiting of login attempts, all access to the
|
||||
API, as well as certain other types of actions that may be involved in
|
||||
abuse. For example, the email confirmation flow, by its nature, needs
|
||||
to allow sending an email to an email address that isn't associated
|
||||
with an existing Zulip account. Limiting the ability of users to
|
||||
trigger such emails helps prevent bad actors from damaging the spam
|
||||
reputation of a Zulip server by sending confirmation emails to random
|
||||
email addresses.
|
||||
|
||||
The default rate limiting rules for a Zulip server will change as we improve
|
||||
the product. A server administrator can browse the current rules using
|
||||
`/home/zulip/deployments/current/scripts/get-django-setting
|
||||
RATE_LIMITING_RULES`; or with comments by reading
|
||||
`DEFAULT_RATE_LIMITING_RULES` in `zproject/default_settings.py`.
|
||||
|
||||
Server administrators can tweak rate limiting in the following ways in
|
||||
`/etc/zulip/settings.py`:
|
||||
|
||||
- The `RATE_LIMITING` setting can be set to `False` to completely
|
||||
disable all rate-limiting.
|
||||
- The `RATE_LIMITING_RULES` setting can be used to override specific
|
||||
rules. See the comment in the file for more specific details on how
|
||||
to do it. After changing the setting, we recommend using
|
||||
`/home/zulip/deployments/current/scripts/get-django-setting
|
||||
RATE_LIMITING_RULES` to verify your changes. You can then restart
|
||||
the Zulip server with `scripts/restart-server` to have the new
|
||||
configuration take effect.
|
||||
- The `RATE_LIMIT_TOR_TOGETHER` setting can be set to `True` to group all
|
||||
known exit nodes of [TOR](https://www.torproject.org/) together for purposes
|
||||
of IP address limiting. Since traffic from a client using TOR is distributed
|
||||
across its exit nodes, without enabling this setting, TOR can otherwise be
|
||||
used to avoid IP-based rate limiting. The updated list of TOR exit nodes
|
||||
is refetched once an hour.
|
||||
- If a user runs into the rate limit for login attempts, a server
|
||||
administrator can clear this state using the
|
||||
`manage.py reset_authentication_attempt_count`
|
||||
[management command][management-commands].
|
||||
|
||||
See also our [API documentation on rate limiting][rate-limit-api].
|
||||
|
||||
[management-commands]: ../production/management-commands.md
|
||||
[rate-limit-api]: https://zulip.com/api/rest-error-handling#rate-limit-exceeded
|
||||
|
||||
## Final notes and security response
|
||||
|
||||
If you find some aspect of Zulip that seems inconsistent with this
|
||||
security model, please report it to security@zulip.com so that we can
|
||||
investigate and coordinate an appropriate security release if needed.
|
||||
|
||||
Zulip security announcements will be sent to
|
||||
zulip-announce@googlegroups.com, so you should subscribe if you are
|
||||
running Zulip in production.
|
@@ -304,7 +304,7 @@ value. Also supported is "[S3 Reduced Redundancy][s3-rr]", by setting
|
||||
|
||||
What compression method to use when storing backups; defaults to `lz4`, which is
|
||||
fast but does not compress particularly well. Other options are `lzma`, `zstd`,
|
||||
and `brotl`; `lzma` provides the best (and slowest) compression, while `zstd`
|
||||
and `brotli`; `lzma` provides the best (and slowest) compression, while `zstd`
|
||||
and `brotli` are middling compromises.
|
||||
|
||||
#### `missing_dictionaries`
|
||||
|
@@ -794,7 +794,7 @@ confirm everything is working correctly.
|
||||
|
||||
3. Follow [Debian's instructions to upgrade the OS][bullseye-upgrade].
|
||||
|
||||
[bullseye-upgrade]: https://www.debian.org/releases/bullseye/amd64/release-notes/ch-upgrading.html
|
||||
[bullseye-upgrade]: https://www.debian.org/releases/bullseye/amd64/release-notes.en.txt
|
||||
|
||||
When prompted for you how to upgrade configuration
|
||||
files for services that Zulip manages like Redis, PostgreSQL,
|
||||
|
@@ -168,7 +168,7 @@ The file uploads bucket should have a policy of:
|
||||
```
|
||||
|
||||
The file-uploads bucket should not be world-readable. See the
|
||||
[documentation on the Zulip security model](security-model.md) for
|
||||
[documentation on the Zulip security model](securing-your-zulip-server.md) for
|
||||
details on the security model for uploaded files.
|
||||
|
||||
However, the avatars bucket is intended to be world-readable, so its
|
||||
|
@@ -81,7 +81,7 @@ preparing a new release.
|
||||
- Email to [zulip-announce](https://groups.google.com/g/zulip-announce)
|
||||
- Email to [zulip-blog-announce](https://groups.google.com/a/zulip.com/g/zulip-blog-announce)
|
||||
- Message in [#announce](https://chat.zulip.org/#narrow/channel/1-announce)
|
||||
- Tweet from [@zulip](https://twitter.com/zulip).
|
||||
- Tweet from [@zulip](https://x.com/zulip).
|
||||
- Toot from [fosstodon.org/@zulip](https://fosstodon.org/@zulip)
|
||||
|
||||
### Post-release
|
||||
|
@@ -48,7 +48,7 @@ to check out your branch.
|
||||
|
||||
- [QuickTime](https://support.apple.com/en-in/HT201066)
|
||||
- [GIPHY](https://giphy.com/apps/giphycapture)
|
||||
- [CloudApp](https://www.getcloudapp.com)
|
||||
- [Zight](https://zight.com)
|
||||
- [Kap](https://getkap.co)
|
||||
- [Gifski](https://sindresorhus.com/gifski)
|
||||
- [Gyazo GIF](https://gyazo.com/en)
|
||||
@@ -57,7 +57,6 @@ to check out your branch.
|
||||
|
||||
- [ScreenToGif](https://www.screentogif.com)
|
||||
- [Gyazo GIF](https://gyazo.com/en)
|
||||
- [Monosnap](https://monosnap.com)
|
||||
|
||||
### Linux
|
||||
|
||||
|
@@ -40,31 +40,32 @@ Generic | Like a normal user account | Automating tasks, bots that listen to all
|
||||
Incoming webhook | Limited to only sending messages into Zulip | Automated notifications into Zulip
|
||||
Outgoing webhook | Generic bot that also receives new messages via HTTP post requests | Third party integrations, most custom bots
|
||||
|
||||
It's generally best to pick the most restricted bot type that is sufficient
|
||||
to do the task at hand. Anyone with the bot's API key can do anything the
|
||||
bot can.
|
||||
A **generic** bot acts like a normal Zulip user that can only access Zulip via
|
||||
the API. There's a handful of actions bots can't take, including creating other
|
||||
bots.
|
||||
|
||||
A few more details:
|
||||
An **outgoing webhook** bot can read direct messages where the bot
|
||||
is a participant, and channel messages where the bot is
|
||||
[mentioned](/help/mention-a-user-or-group). When the bot is DM'd or
|
||||
mentioned, it POSTs the message content to a URL of your choice. The
|
||||
POST request format can be in a Zulip format or a Slack-compatible
|
||||
format. This is the preferred bot type for interactive bots built on
|
||||
top of Zulip Botserver.
|
||||
|
||||
* Bots can send messages to any channel that their owner can,
|
||||
inheriting their owner's [sending permissions](/help/channel-posting-policy).
|
||||
* Bots can be subscribed to channels, and their role can be modified if
|
||||
they need to have permission to do administrative actions.
|
||||
* [Channel permissions](/help/channel-permissions) are the same for bots
|
||||
as for other users. Therefore, for private channels with protected
|
||||
history, a bot can only access messages sent after it was subscribed
|
||||
to the channel.
|
||||
* **Generic**: A generic bot is like a normal Zulip user account that
|
||||
cannot log in via a browser. Note that if you truly want to
|
||||
impersonate yourself (e.g., write messages that come from your Zulip
|
||||
account), you'll need to use your **personal API key**.
|
||||
* **Outgoing webhook**: The bot can read direct messages where the bot
|
||||
is a participant, and channel messages where the bot is
|
||||
[mentioned](/help/mention-a-user-or-group). When the bot is DM'd or
|
||||
mentioned, it POSTs the message content to a URL of your choice. The
|
||||
POST request format can be in a Zulip format or a Slack-compatible
|
||||
format. This is the preferred bot type for interactive bots built on
|
||||
top of Zulip Botserver.
|
||||
Use the most limited bot type that supports your integration. Anyone with the
|
||||
bot's API key can do anything the bot can, so giving bots unnecessary
|
||||
permissions can expose your organization to unnecessary risk.
|
||||
|
||||
## Channel permissions for bots
|
||||
|
||||
Bots can be subscribed to channels, and assigned [channel
|
||||
permissions](/help/channel-permissions) just like human users. In private
|
||||
channels with protected history, a bot can only access messages sent after it
|
||||
was subscribed to the channel.
|
||||
|
||||
Bots can send messages to any channel that their owner can, inheriting their
|
||||
owner's [sending permissions](/help/channel-posting-policy). You can give a bot
|
||||
channel management permissions, just like you would for a human user.
|
||||
|
||||
## Adding bots
|
||||
|
||||
@@ -73,6 +74,20 @@ Zulip organization, but administrators can
|
||||
[restrict bot creation](/help/restrict-bot-creation). Any bot that is added
|
||||
is visible and available for anyone to use.
|
||||
|
||||
## Integrations that act on behalf of users
|
||||
|
||||
If you want an integration to impersonate you (e.g., write messages that come
|
||||
from your Zulip account), use your [personal API key](/api/api-keys), rather
|
||||
than a bot's API key. You won't need to create a bot.
|
||||
|
||||
If you need a bot to send messages on behalf of multiple users, ask [Zulip
|
||||
support](mailto:support@zulip.com) or your server administrator to run the
|
||||
`manage.py change_user_role can_forge_sender` command to give a bot
|
||||
permission to send messages as users in your organization. Bots with the
|
||||
`can_forge_sender` permission can also see the names of all channels,
|
||||
including private channels. This is important for implementing integrations
|
||||
like the Jabber and IRC mirrors.
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Integrations overview](/help/integrations-overview)
|
||||
|
@@ -14,8 +14,14 @@ account.
|
||||
|
||||
{settings_tab|account-and-privacy}
|
||||
|
||||
1. Under **Account**, click on the password field (it should look like `********`).
|
||||
1. Under **Account**, click **Change your password**.
|
||||
|
||||
1. Enter your old password and your new password, and click **Change**.
|
||||
|
||||
{end_tabs}
|
||||
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Logging in](/help/logging-in)
|
||||
* [Logging out](/help/logging-out)
|
||||
|
@@ -69,6 +69,12 @@ for your organization.
|
||||
[community-norms]: https://zulip.com/development-community/#community-norms
|
||||
[development-community-channels]: https://zulip.com/development-community/#channels-for-zulip-users-and-administrators
|
||||
|
||||
## Security
|
||||
|
||||
If you believe you've identified a security issue, please report it to Zulip's
|
||||
security team at [security@zulip.com](mailto:security@zulip.com) as soon as
|
||||
possible, so that we can address it and make a responsible disclosure.
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Zulip Cloud billing](/help/zulip-cloud-billing)
|
||||
|
@@ -2,7 +2,10 @@
|
||||
|
||||
**Direct messages (DMs)** are conversations with other users that happen outside
|
||||
of a [channel](/help/introduction-to-channels). They are convenient for 1:1 and
|
||||
small group conversations.
|
||||
small group conversations. Direct messages are private to conversation participants. Administrators may be
|
||||
able to [export](/help/export-your-organization) your DMs in a corporate
|
||||
organization, or [with your
|
||||
permission](/help/export-your-organization#configure-whether-administrators-can-export-your-private-data).
|
||||
|
||||
If you find yourself frequently conversing with the same person or group, it
|
||||
often works best to [create a private channel](/help/create-a-channel) for your
|
||||
|
@@ -737,7 +737,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="comparison-table-feature">
|
||||
<a href="https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#plug-and-play-sso-google-github-gitlab">SSO with Microsoft Entra ID</a>
|
||||
<a href="https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#microsoft-entra-id">SSO with Microsoft Entra ID</a>
|
||||
</td>
|
||||
<td class="comparison-value-negative cloud-cell"><i class="icon icon-x"></i></td>
|
||||
<td class="comparison-value-positive cloud-cell"><i class="icon icon-check"></i></td>
|
||||
|
@@ -4,9 +4,11 @@ priority.
|
||||
|
||||
## Security basics
|
||||
|
||||
- All Zulip clients (web, mobile, desktop, terminal, and integrations)
|
||||
require TLS encryption and authentication over HTTPS for all data
|
||||
transmission between clients and the server, both on LAN and the Internet.
|
||||
- All Zulip clients (web, mobile, desktop, terminal, and integrations) require
|
||||
TLS encryption and authentication over HTTPS for all data transmission between
|
||||
clients and the server, both on LAN and the Internet. By default, all Zulip
|
||||
services talk to each other either via a localhost connection or using an
|
||||
encrypted SSL connection.
|
||||
- All Zulip Cloud customer data is encrypted at rest. Self-hosted Zulip can be
|
||||
configured for encryption at rest via your hosting provider, or by setting up
|
||||
hardware and software disk encryption of the database and other data storage
|
||||
@@ -20,6 +22,8 @@ priority.
|
||||
[deployed on multiple servers](https://zulip.readthedocs.io/en/latest/production/deployment.html),
|
||||
all connections between parts of the Zulip infrastructure can be secured
|
||||
with TLS or SSH.
|
||||
- Zulip requires CSRF tokens in all interactions with the web API to
|
||||
prevent CSRF attacks.
|
||||
- Message content can be
|
||||
[excluded from mobile push notifications][redact-content],
|
||||
to avoid displaying message content on locked mobile screens, and to
|
||||
|
@@ -576,12 +576,6 @@ export function initialize() {
|
||||
});
|
||||
|
||||
$("textarea#compose-textarea").on("focus", () => {
|
||||
// To shortcut a delay otherwise introduced when the topic
|
||||
// input is blurred, we immediately update the topic's
|
||||
// displayed text and compose-area placeholder when the
|
||||
// compose textarea is focused.
|
||||
const $input = $("input#stream_message_recipient_topic");
|
||||
compose_recipient.update_topic_displayed_text($input.val());
|
||||
compose_recipient.update_compose_area_placeholder_text();
|
||||
compose_fade.do_update_all();
|
||||
if (narrow_state.narrowed_by_reply()) {
|
||||
@@ -611,25 +605,20 @@ export function initialize() {
|
||||
compose_validate.validate_and_update_send_button_status();
|
||||
});
|
||||
|
||||
// To track delayed effects originating from the "blur" event
|
||||
// and its use of setTimeout, we need to set up a variable to
|
||||
// reference the timeout's ID across events.
|
||||
let recipient_focused_timeout;
|
||||
$("input#stream_message_recipient_topic").on("focus", () => {
|
||||
// We don't want the `recently-focused` class removed via
|
||||
// a setTimeout from the "blur" event, if we're suddenly
|
||||
// focused again.
|
||||
clearTimeout(recipient_focused_timeout);
|
||||
const $compose_recipient = $("#compose-recipient");
|
||||
const $input = $("input#stream_message_recipient_topic");
|
||||
compose_recipient.update_topic_displayed_text($input.val(), true);
|
||||
compose_recipient.update_compose_area_placeholder_text();
|
||||
// When the topic input is focused, we no longer treat
|
||||
// the recipient row as low attention, as we assume the user
|
||||
// is doing something that requires keeping attention called
|
||||
// to the recipient row.
|
||||
// to the recipient row
|
||||
compose_recipient.set_high_attention_recipient_row();
|
||||
$compose_recipient.addClass("recently-focused");
|
||||
|
||||
$("input#stream_message_recipient_topic").one("blur", () => {
|
||||
compose_recipient.update_topic_displayed_text($input.val());
|
||||
compose_recipient.update_compose_area_placeholder_text();
|
||||
});
|
||||
});
|
||||
|
||||
$("input#stream_message_recipient_topic").on("input", () => {
|
||||
@@ -638,41 +627,14 @@ export function initialize() {
|
||||
});
|
||||
|
||||
$("#private_message_recipient").on("focus", () => {
|
||||
// We don't want the `.recently-focused` class removed via
|
||||
// setTimeout from the "blur" event, if we're suddenly
|
||||
// focused again.
|
||||
clearTimeout(recipient_focused_timeout);
|
||||
const $compose_recipient = $("#compose-recipient");
|
||||
// When the DM input is focused, we no longer treat
|
||||
// the recipient row as low attention, as we assume the user
|
||||
// is doing something that requires keeping attention called
|
||||
// to the recipient row
|
||||
compose_recipient.set_high_attention_recipient_row();
|
||||
$compose_recipient.addClass("recently-focused");
|
||||
});
|
||||
|
||||
$("input#stream_message_recipient_topic, #private_message_recipient").on("blur", () => {
|
||||
const $compose_recipient = $("#compose-recipient");
|
||||
const $input = $("input#stream_message_recipient_topic");
|
||||
// To correct for an edge case when clearing the topic box
|
||||
// via the left sidebar, we do the following actions after a
|
||||
// delay; these will not have an effect for DMs, and so can
|
||||
// safely be referenced here. Note, too, that if focus shifts
|
||||
// immediately from the topic box to the compose textarea,
|
||||
// we update these things immediately so that no delay is
|
||||
// apparent on the topic's displayed text or the placeholder
|
||||
// in the empty compose textarea.
|
||||
// Also, in case a user quickly opens and closes the compose
|
||||
// box, we need to clear a previously set timeout before
|
||||
// setting a new one. Otherwise, the compose box can open
|
||||
// in a strange state displaying *general chat* and italicizing
|
||||
// the topic input.
|
||||
clearTimeout(recipient_focused_timeout);
|
||||
recipient_focused_timeout = setTimeout(() => {
|
||||
compose_recipient.update_topic_displayed_text($input.val());
|
||||
compose_recipient.update_compose_area_placeholder_text();
|
||||
$compose_recipient.removeClass("recently-focused");
|
||||
}, 500);
|
||||
compose_recipient.update_recipient_row_attention_level();
|
||||
});
|
||||
|
||||
|
@@ -1247,10 +1247,9 @@ textarea.new_message_textarea {
|
||||
interactions (e.g., Shift-Tabbing from the compose textarea
|
||||
to the topic box) show instant changes, so we don't need to
|
||||
accommodate them here, which we prevent by applying the
|
||||
transitions only when focus isn't within the recipient row,
|
||||
or hasn't recently been within the topic box. */
|
||||
transitions only when focus isn't within the recipient row. */
|
||||
#compose.compose-box-open {
|
||||
.low-attention-recipient-row:not(.recently-focused, :focus-within) {
|
||||
.low-attention-recipient-row:hover:not(:focus-within) {
|
||||
#compose_select_recipient_widget,
|
||||
#compose_recipient_box,
|
||||
#compose-direct-recipient .pill-container {
|
||||
|
@@ -243,7 +243,7 @@ AUTH_LDAP_USER_ATTR_MAP = {
|
||||
#
|
||||
## A stable unique identifier for a user allows Zulip to
|
||||
## automatically handle email address changes.
|
||||
## See https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#identifying-user-accounts-via-a-unique-ldap-attribute
|
||||
## See https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#synchronizing-email-addresses
|
||||
# "unique_account_id": "objectSid",
|
||||
##
|
||||
## Profile pictures can be pulled from the LDAP "thumbnailPhoto"/"jpegPhoto" field.
|
||||
@@ -580,7 +580,7 @@ SOCIAL_AUTH_SAML_SUPPORT_CONTACT = {
|
||||
## into Zulip or to fetch users' API keys. The JWT secret key and
|
||||
## algorithm must be configured here.
|
||||
##
|
||||
## See https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#jwt
|
||||
## See https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#json-web-tokens-jwt
|
||||
# JWT_AUTH_KEYS = {
|
||||
# # Subdomain for which this JWT configuration will apply.
|
||||
# "zulip": {
|
||||
|
Reference in New Issue
Block a user