From e0d21bc54ab0d061ea6daab9a5088020a8c7dc7f Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 1 Feb 2023 12:30:13 +0100 Subject: [PATCH 01/11] Replace `setWhitelist` service in with local lists in brig.yaml --- .../SQPIT-405-make-whitelist-local | 1 + .../developer/reference/user/activation.md | 17 ++--- services/brig/brig.integration.yaml | 4 ++ services/brig/src/Brig/API/Handler.hs | 14 ++--- services/brig/src/Brig/Options.hs | 5 +- services/brig/src/Brig/Whitelist.hs | 62 +++++-------------- 6 files changed, 40 insertions(+), 63 deletions(-) create mode 100644 changelog.d/0-release-notes/SQPIT-405-make-whitelist-local diff --git a/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local b/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local new file mode 100644 index 00000000000..ca5ba56ecaa --- /dev/null +++ b/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local @@ -0,0 +1 @@ +In (the unlikely) case your server config file contains `setWhitelist:`, you need to change this before the upgrade! It used to refer to a whitelisting service, which is now replaced with a local list of allowed domains and phone numbers. \ No newline at end of file diff --git a/docs/src/developer/reference/user/activation.md b/docs/src/developer/reference/user/activation.md index 723457ca7e9..7e522efd14c 100644 --- a/docs/src/developer/reference/user/activation.md +++ b/docs/src/developer/reference/user/activation.md @@ -137,17 +137,20 @@ X-Zeta-Code: 123456 ## Phone/email whitelist (RefActivationWhitelist)= -The backend can be configured to only allow specific phone numbers or email addresses to register. The following options have to be set in `brig.yaml`: +The backend can be configured to only allow specific phone number prefixes and email address domains to register. The following options have to be set in `brig.yaml`: ```yaml optSettings: - setWhitelist: - whitelistUrl: ... # Checker URL - whitelistUser: ... # Basic auth username - whitelistPass: ... # Basic auth password + setWhitelistEmailDomains: + - wire.com + - example.com + - notagoodexample.com + setWhitelistPhonePrefixes: + - +49 + - +1555555 ``` -When those options are present, the backend will do a GET request at `?email=...` or `?mobile=...` for every activation request it receives. It will expect either status code 200 ("everything good") or 404 ("provided email/phone is not on the whitelist"). +When those options are present, the backend will match every activation request against these lists. If an email address or phone number are rejected by the whitelist, `POST /activate/send` or `POST /register` will return `403 Forbidden`: @@ -158,5 +161,3 @@ If an email address or phone number are rejected by the whitelist, `POST /activa "message": "Unauthorized e-mail address or phone number." } ``` - -Currently emails at `@wire.com` are always considered whitelisted, regardless of the whitelist service's response. diff --git a/services/brig/brig.integration.yaml b/services/brig/brig.integration.yaml index 41b4287f9f7..1f0e8535363 100644 --- a/services/brig/brig.integration.yaml +++ b/services/brig/brig.integration.yaml @@ -193,6 +193,10 @@ optSettings: setDpopTokenExpirationTimeSecs: 300 # 5 minutes setPublicKeyBundle: test/resources/jwt/ed25519_bundle.pem setEnableMLS: true + setWhitelistEmailDomains: + - wire.com + setWhitelistPhonePrefixes: + - +1555555 logLevel: Warn # ^ NOTE: We log too much in brig, if we set this to Info like other services, running tests diff --git a/services/brig/src/Brig/API/Handler.hs b/services/brig/src/Brig/API/Handler.hs index 5d29b9a2797..2f80fc374b2 100644 --- a/services/brig/src/Brig/API/Handler.hs +++ b/services/brig/src/Brig/API/Handler.hs @@ -31,13 +31,13 @@ module Brig.API.Handler ) where -import Bilge (MonadHttp, RequestId (..)) +import Bilge (RequestId (..)) import Brig.API.Error import qualified Brig.AWS as AWS import Brig.App import Brig.CanonicalInterpreter (BrigCanonicalEffects, runBrigToIO) import Brig.Email (Email) -import Brig.Options (setWhitelist) +import Brig.Options (setWhitelistEmailDomains, setWhitelistPhonePrefixes) import Brig.Phone (Phone, PhoneException (..)) import qualified Brig.Whitelist as Whitelist import Control.Error @@ -171,14 +171,12 @@ parseJsonBody req = parseBody req !>> StdError . badRequest checkWhitelist :: Either Email Phone -> (Handler r) () checkWhitelist = wrapHttpClientE . checkWhitelistWithError (StdError whitelistError) -checkWhitelistWithError :: (Monad m, MonadReader Env m, MonadIO m, Catch.MonadMask m, MonadHttp m, MonadError e m) => e -> Either Email Phone -> m () +checkWhitelistWithError :: (MonadReader Env m, MonadError e m) => e -> Either Email Phone -> m () checkWhitelistWithError e key = do ok <- isWhiteListed key unless ok (throwError e) -isWhiteListed :: (Monad m, MonadReader Env m, MonadIO m, Catch.MonadMask m, MonadHttp m) => Either Email Phone -> m Bool +isWhiteListed :: (MonadReader Env m) => Either Email Phone -> m Bool isWhiteListed key = do - eb <- setWhitelist <$> view settings - case eb of - Nothing -> pure True - Just b -> Whitelist.verify b key + env <- view settings + pure $ Whitelist.verify (setWhitelistEmailDomains env) (setWhitelistPhonePrefixes env) key diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index 941a683aba1..f6f0556d766 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -24,7 +24,7 @@ module Brig.Options where import Brig.Queue.Types (Queue (..)) import Brig.SMTP (SMTPConnType (..)) import Brig.User.Auth.Cookie.Limit -import Brig.Whitelist (Whitelist (..)) +import Brig.Whitelist (WhitelistEmailDomains (..), WhitelistPhonePrefixes (..)) import qualified Brig.ZAuth as ZAuth import Control.Applicative import qualified Control.Lens as Lens @@ -492,7 +492,8 @@ data Settings = Settings -- | STOMP broker credentials setStomp :: !(Maybe FilePathSecrets), -- | Whitelist of allowed emails/phones - setWhitelist :: !(Maybe Whitelist), + setWhitelistEmailDomains :: !(Maybe WhitelistEmailDomains), + setWhitelistPhonePrefixes :: !(Maybe WhitelistPhonePrefixes), -- | Max. number of sent/accepted -- connections per user setUserMaxConnections :: !Int64, diff --git a/services/brig/src/Brig/Whitelist.hs b/services/brig/src/Brig/Whitelist.hs index 9f9bac98da7..8eed5f95e2b 100644 --- a/services/brig/src/Brig/Whitelist.hs +++ b/services/brig/src/Brig/Whitelist.hs @@ -19,60 +19,32 @@ -- -- Email/phone whitelist. module Brig.Whitelist - ( Whitelist (..), + ( WhitelistEmailDomains (..), + WhitelistPhonePrefixes (..), verify, ) where -import Bilge.IO -import Bilge.Request -import Bilge.Response -import Bilge.Retry -import Control.Monad.Catch (MonadMask, throwM) -import Control.Retry import Data.Aeson -import Data.Text -import Data.Text.Encoding (encodeUtf8) +import qualified Data.Text as Text import Imports -import Network.HTTP.Client (HttpExceptionContent (..)) import Wire.API.User.Identity -- | A service providing a whitelist of allowed email addresses and phone numbers -data Whitelist = Whitelist - { -- | Service URL - whitelistUrl :: !Text, - -- | Username - whitelistUser :: !Text, - -- | Password - whitelistPass :: !Text - } +data WhitelistEmailDomains = WhitelistEmailDomains [Text] deriving (Show, Generic) -instance FromJSON Whitelist +instance FromJSON WhitelistEmailDomains --- | Do a request to the whitelist service and verify that the provided email/phone address is --- whitelisted. -verify :: (MonadIO m, MonadMask m, MonadHttp m) => Whitelist -> Either Email Phone -> m Bool -verify (Whitelist url user pass) key = - if isKnownDomain key - then pure True - else recovering x3 httpHandlers . const $ do - rq <- parseRequest $ unpack url - rsp <- get' rq $ req (encodeUtf8 user) (encodeUtf8 pass) - case statusCode rsp of - 200 -> pure True - 404 -> pure False - _ -> - throwM $ - HttpExceptionRequest rq (StatusCodeException (rsp {responseBody = ()}) mempty) - where - isKnownDomain (Left e) = emailDomain e == "wire.com" - isKnownDomain _ = False - urlEmail = queryItem "email" . encodeUtf8 . fromEmail - urlPhone = queryItem "mobile" . encodeUtf8 . fromPhone - req u p = - port 443 - . secure - . either urlEmail urlPhone key - . applyBasicAuth u p - x3 = limitRetries 3 <> exponentialBackoff 100000 +data WhitelistPhonePrefixes = WhitelistPhonePrefixes [Text] + deriving (Show, Generic) + +instance FromJSON WhitelistPhonePrefixes + +-- | Consult the whitelist settings in brig's config file and verify that the provided +-- email/phone address is whitelisted. +verify :: Maybe WhitelistEmailDomains -> Maybe WhitelistPhonePrefixes -> Either Email Phone -> Bool +verify (Just (WhitelistEmailDomains allowed)) _ (Left email) = emailDomain email `elem` allowed +verify _ (Just (WhitelistPhonePrefixes allowed)) (Right phone) = any (`Text.isPrefixOf` fromPhone phone) allowed +verify Nothing _ (Left _) = True +verify _ Nothing (Right _) = True From 02942f53df0586f9a3f8963ffb95c3045a3e4f31 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 1 Feb 2023 12:35:27 +0100 Subject: [PATCH 02/11] rm trailing whitespace. --- docs/src/developer/reference/user/activation.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/src/developer/reference/user/activation.md b/docs/src/developer/reference/user/activation.md index 7e522efd14c..af37e412e09 100644 --- a/docs/src/developer/reference/user/activation.md +++ b/docs/src/developer/reference/user/activation.md @@ -10,7 +10,7 @@ A user is called _activated_ they have a verified identity -- e.g. a phone numbe A user that has been provisioned via single sign-on is always considered to be activated. -## Activated vs. non-activated users +## Activated vs. non-activated users (RefActivationBenefits)= Non-activated users can not [connect](connection.md) to others, nor can connection requests be made to anonymous accounts from verified accounts. As a result: @@ -19,10 +19,10 @@ Non-activated users can not [connect](connection.md) to others, nor can connecti The only flow where it makes sense for non-activated users to exist is the [wireless flow](RefRegistrationWireless) used for [guest rooms](https://wire.com/en/features/encrypted-guest-rooms/) -## API +## API (RefActivationApi)= -### Requesting an activation code +### Requesting an activation code (RefActivationRequest)= During the [standard registration flow](RefRegistrationStandard), the user submits an email address or phone number by making a request to `POST /activate/send`. A six-digit activation code will be sent to that email address / phone number. Sample request and response: @@ -44,7 +44,7 @@ The user can submit the activation code during registration to prove that they o The same `POST /activate/send` endpoint can be used to re-request an activation code. Please use this ability sparingly! To avoid unnecessary activation code requests, users should be warned that it might take up to a few minutes for an email or text message to arrive. -### Activating an existing account +### Activating an existing account (RefActivationSubmit)= If the account [has not been activated during verification](RefRegistrationNoPreverification), it can be activated afterwards by submitting an activation code to `POST /activate`. Sample request and response: @@ -80,7 +80,7 @@ If the email or phone has been verified already, `POST /activate` will return st There is a maximum of 3 activation attempts per activation code. On the third failed attempt the code is invalidated and a new one must be requested. -### Activation event +### Activation event (RefActivationEvent)= When the user becomes activated, they receive an event: @@ -92,7 +92,7 @@ When the user becomes activated, they receive an event: } ``` -### Detecting activation in the self profile +### Detecting activation in the self profile (RefActivationProfile)= In addition to the [activation event](RefActivationEvent), activation can be detected by polling the self profile: @@ -114,7 +114,7 @@ GET /self If the profile includes `"email"` or `"phone"`, the account is activated. -## Automating activation via email +## Automating activation via email (RefActivationEmailHeaders)= Our email verification messages contain headers that can be used to automate the activation process. @@ -134,7 +134,7 @@ X-Zeta-Key: ... X-Zeta-Code: 123456 ``` -## Phone/email whitelist +## Phone/email whitelist (RefActivationWhitelist)= The backend can be configured to only allow specific phone number prefixes and email address domains to register. The following options have to be set in `brig.yaml`: From c10ae0e6fdd1942eb46f72da3625e3534be88beb Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 1 Feb 2023 12:44:04 +0100 Subject: [PATCH 03/11] Reference docs in changelog. --- changelog.d/0-release-notes/SQPIT-405-make-whitelist-local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local b/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local index ca5ba56ecaa..2ece3e29622 100644 --- a/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local +++ b/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local @@ -1 +1 @@ -In (the unlikely) case your server config file contains `setWhitelist:`, you need to change this before the upgrade! It used to refer to a whitelisting service, which is now replaced with a local list of allowed domains and phone numbers. \ No newline at end of file +In (the unlikely) case your server config file contains `setWhitelist:`, you need to change this before the upgrade! It used to refer to a whitelisting service, which is now replaced with a local list of allowed domains and phone numbers. See [docs](https://docs.wire.com/developer/reference/user/activation.html?highlight=whitelist#phone-email-whitelist) for details. \ No newline at end of file From 8f2208f3a75e7fa277b9b75adcfcaaeeafff8883 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 8 Feb 2023 15:43:47 +0100 Subject: [PATCH 04/11] Better terminology. --- docs/src/developer/reference/user/activation.md | 4 ++-- services/brig/brig.integration.yaml | 4 ++-- services/brig/src/Brig/API/Handler.hs | 4 ++-- services/brig/src/Brig/Options.hs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/src/developer/reference/user/activation.md b/docs/src/developer/reference/user/activation.md index af37e412e09..8a2a612a242 100644 --- a/docs/src/developer/reference/user/activation.md +++ b/docs/src/developer/reference/user/activation.md @@ -141,11 +141,11 @@ The backend can be configured to only allow specific phone number prefixes and e ```yaml optSettings: - setWhitelistEmailDomains: + setAllowlistEmailDomains: - wire.com - example.com - notagoodexample.com - setWhitelistPhonePrefixes: + setAllowlistPhonePrefixes: - +49 - +1555555 ``` diff --git a/services/brig/brig.integration.yaml b/services/brig/brig.integration.yaml index 1f0e8535363..e0af13540b4 100644 --- a/services/brig/brig.integration.yaml +++ b/services/brig/brig.integration.yaml @@ -193,9 +193,9 @@ optSettings: setDpopTokenExpirationTimeSecs: 300 # 5 minutes setPublicKeyBundle: test/resources/jwt/ed25519_bundle.pem setEnableMLS: true - setWhitelistEmailDomains: + setAllowlistEmailDomains: - wire.com - setWhitelistPhonePrefixes: + setAllowlistPhonePrefixes: - +1555555 logLevel: Warn diff --git a/services/brig/src/Brig/API/Handler.hs b/services/brig/src/Brig/API/Handler.hs index 2f80fc374b2..8c32fb01c5c 100644 --- a/services/brig/src/Brig/API/Handler.hs +++ b/services/brig/src/Brig/API/Handler.hs @@ -37,7 +37,7 @@ import qualified Brig.AWS as AWS import Brig.App import Brig.CanonicalInterpreter (BrigCanonicalEffects, runBrigToIO) import Brig.Email (Email) -import Brig.Options (setWhitelistEmailDomains, setWhitelistPhonePrefixes) +import Brig.Options (setAllowlistEmailDomains, setAllowlistPhonePrefixes) import Brig.Phone (Phone, PhoneException (..)) import qualified Brig.Whitelist as Whitelist import Control.Error @@ -179,4 +179,4 @@ checkWhitelistWithError e key = do isWhiteListed :: (MonadReader Env m) => Either Email Phone -> m Bool isWhiteListed key = do env <- view settings - pure $ Whitelist.verify (setWhitelistEmailDomains env) (setWhitelistPhonePrefixes env) key + pure $ Whitelist.verify (setAllowlistEmailDomains env) (setAllowlistPhonePrefixes env) key diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index f6f0556d766..2b3dd140d15 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -492,8 +492,8 @@ data Settings = Settings -- | STOMP broker credentials setStomp :: !(Maybe FilePathSecrets), -- | Whitelist of allowed emails/phones - setWhitelistEmailDomains :: !(Maybe WhitelistEmailDomains), - setWhitelistPhonePrefixes :: !(Maybe WhitelistPhonePrefixes), + setAllowlistEmailDomains :: !(Maybe WhitelistEmailDomains), + setAllowlistPhonePrefixes :: !(Maybe WhitelistPhonePrefixes), -- | Max. number of sent/accepted -- connections per user setUserMaxConnections :: !Int64, From 126fc96e283bb4b82d2bdab5932cee5a61e77861 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 8 Feb 2023 15:50:12 +0100 Subject: [PATCH 05/11] Explain migration path in changelog. --- changelog.d/0-release-notes/SQPIT-405-make-whitelist-local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local b/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local index 2ece3e29622..5d9bd5384bf 100644 --- a/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local +++ b/changelog.d/0-release-notes/SQPIT-405-make-whitelist-local @@ -1 +1 @@ -In (the unlikely) case your server config file contains `setWhitelist:`, you need to change this before the upgrade! It used to refer to a whitelisting service, which is now replaced with a local list of allowed domains and phone numbers. See [docs](https://docs.wire.com/developer/reference/user/activation.html?highlight=whitelist#phone-email-whitelist) for details. \ No newline at end of file +In (the unlikely) case your server config file contains `setWhitelist:`, you need to change this before the upgrade! It used to refer to a whitelisting service, which is now replaced with a local list of allowed domains and phone numbers. See [docs](https://docs.wire.com/developer/reference/user/activation.html?highlight=whitelist#phone-email-whitelist) for details. Migration path: add new config fields; upgrade, remove old config fields. \ No newline at end of file From 53b5ad676fd310d87cbe4bafa576423d475e80f3 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 8 Feb 2023 16:01:19 +0100 Subject: [PATCH 06/11] Fixup --- charts/brig/templates/configmap.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/charts/brig/templates/configmap.yaml b/charts/brig/templates/configmap.yaml index a62139035ab..45f664e8655 100644 --- a/charts/brig/templates/configmap.yaml +++ b/charts/brig/templates/configmap.yaml @@ -270,8 +270,11 @@ data: {{- if .setSftListAllServers }} setSftListAllServers: {{ .setSftListAllServers }} {{- end }} - {{- if .setWhitelist }} - setWhitelist: {{ toYaml .setWhitelist | nindent 8 }} + {{- if .setAllowlistEmailDomains }} + setAllowlistEmailDomains: {{ toYaml .setAllowlistEmailDomains | nindent 8 }} + {{- end }} + {{- if .setAllowlistPhonePrefixes }} + setAllowlistPhonePrefixes: {{ toYaml .setAllowlistPhonePrefixes | nindent 8 }} {{- end }} {{- if .setFeatureFlags }} setFeatureFlags: {{ toYaml .setFeatureFlags | nindent 8 }} From edae50fb8fee750a48322a4a2256ae1d3b9ea822 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 8 Feb 2023 16:04:55 +0100 Subject: [PATCH 07/11] Tweak PR guidelines. --- docs/src/developer/developer/pr-guidelines.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/src/developer/developer/pr-guidelines.md b/docs/src/developer/developer/pr-guidelines.md index 1afeb2c56e4..e54a54f4a14 100644 --- a/docs/src/developer/developer/pr-guidelines.md +++ b/docs/src/developer/developer/pr-guidelines.md @@ -84,7 +84,7 @@ If a PR adds new configuration options for say brig, the following files need to * [ ] The integration test config: `services/brig/brig.integration.yaml` * [ ] The charts: `charts/brig/templates/configmap.yaml` * [ ] The default values: `charts/brig/values.yaml` -* [ ] The values files for CI: `hack/helm_vars/wire-server/values.yaml` +* [ ] The values files for CI: `hack/helm_vars/wire-server/values.yaml.gotmpl` * [ ] The configuration docs: `docs/src/developer/reference/config-options.md` If any new configuration value is required and has no default, then: @@ -100,8 +100,9 @@ Remove them with the PR from wire-server `./charts` folder, as charts are linked ### Renaming configuration flags -Avoid doing this. If you must, see Removing/adding sections above. But please note that all people who have an installation of wire also may have overridden any of the configuration option you may wish to change the name of. As this is not type checked, it's very error prone and people may find themselves with default configuration values being used instead of their intended configuration settings. Guideline: only rename for good reasons, not for aesthetics; or be prepared to spend a significant -amount on documenting and communication about this change. +Avoid doing this, it's usually viable to introduce an at-least-equally-good name and remove the old one, that admins can first add the new options, then uprade the software, then remove the old ones. + +If you must, see Removing/adding sections above. But please note that all people who have an installation of wire also may have overridden any of the configuration option you may wish to change the name of. As this is not type checked, it's very error prone and people may find themselves with default configuration values being used instead of their intended configuration settings. Guideline: only rename for good reasons, not for aesthetics; or be prepared to spend a significant amount on documenting and communication about this change. ## Changes to developer workflow From 99c1a9f7b2c7b2041d16f4fb424c2b0075aa8a90 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 8 Feb 2023 16:05:02 +0100 Subject: [PATCH 08/11] rm trailing whitespace. --- docs/src/developer/developer/pr-guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/developer/developer/pr-guidelines.md b/docs/src/developer/developer/pr-guidelines.md index e54a54f4a14..be0bf1f01b1 100644 --- a/docs/src/developer/developer/pr-guidelines.md +++ b/docs/src/developer/developer/pr-guidelines.md @@ -18,7 +18,7 @@ See `docs/legacy/developer/changelog.md` for more information. ## Schema migrations -Don't delete columns that are still used by versions that are deployed. If you delete columns then the old version will fail in the deployment process. Rather than deleting keep the unused columns around and comment them as being discontinued in the schema migration code. +Don't delete columns that are still used by versions that are deployed. If you delete columns then the old version will fail in the deployment process. Rather than deleting keep the unused columns around and comment them as being discontinued in the schema migration code. If a cassandra schema migration has been added then add this to the checklist: From b1d530c87955779a5ef5559125f99c3bfb0e6bea Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 8 Feb 2023 17:07:21 +0100 Subject: [PATCH 09/11] Oops. --- services/brig/src/Brig/Options.hs | 6 +++--- services/brig/src/Brig/Whitelist.hs | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index 2b3dd140d15..d7030ecc18f 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -24,7 +24,7 @@ module Brig.Options where import Brig.Queue.Types (Queue (..)) import Brig.SMTP (SMTPConnType (..)) import Brig.User.Auth.Cookie.Limit -import Brig.Whitelist (WhitelistEmailDomains (..), WhitelistPhonePrefixes (..)) +import Brig.Whitelist (AllowlistEmailDomains (..), AllowlistPhonePrefixes (..)) import qualified Brig.ZAuth as ZAuth import Control.Applicative import qualified Control.Lens as Lens @@ -492,8 +492,8 @@ data Settings = Settings -- | STOMP broker credentials setStomp :: !(Maybe FilePathSecrets), -- | Whitelist of allowed emails/phones - setAllowlistEmailDomains :: !(Maybe WhitelistEmailDomains), - setAllowlistPhonePrefixes :: !(Maybe WhitelistPhonePrefixes), + setAllowlistEmailDomains :: !(Maybe AllowlistEmailDomains), + setAllowlistPhonePrefixes :: !(Maybe AllowlistPhonePrefixes), -- | Max. number of sent/accepted -- connections per user setUserMaxConnections :: !Int64, diff --git a/services/brig/src/Brig/Whitelist.hs b/services/brig/src/Brig/Whitelist.hs index 8eed5f95e2b..fe110eaec23 100644 --- a/services/brig/src/Brig/Whitelist.hs +++ b/services/brig/src/Brig/Whitelist.hs @@ -19,8 +19,8 @@ -- -- Email/phone whitelist. module Brig.Whitelist - ( WhitelistEmailDomains (..), - WhitelistPhonePrefixes (..), + ( AllowlistEmailDomains (..), + AllowlistPhonePrefixes (..), verify, ) where @@ -31,20 +31,20 @@ import Imports import Wire.API.User.Identity -- | A service providing a whitelist of allowed email addresses and phone numbers -data WhitelistEmailDomains = WhitelistEmailDomains [Text] +data AllowlistEmailDomains = AllowlistEmailDomains [Text] deriving (Show, Generic) -instance FromJSON WhitelistEmailDomains +instance FromJSON AllowlistEmailDomains -data WhitelistPhonePrefixes = WhitelistPhonePrefixes [Text] +data AllowlistPhonePrefixes = AllowlistPhonePrefixes [Text] deriving (Show, Generic) -instance FromJSON WhitelistPhonePrefixes +instance FromJSON AllowlistPhonePrefixes -- | Consult the whitelist settings in brig's config file and verify that the provided -- email/phone address is whitelisted. -verify :: Maybe WhitelistEmailDomains -> Maybe WhitelistPhonePrefixes -> Either Email Phone -> Bool -verify (Just (WhitelistEmailDomains allowed)) _ (Left email) = emailDomain email `elem` allowed -verify _ (Just (WhitelistPhonePrefixes allowed)) (Right phone) = any (`Text.isPrefixOf` fromPhone phone) allowed +verify :: Maybe AllowlistEmailDomains -> Maybe AllowlistPhonePrefixes -> Either Email Phone -> Bool +verify (Just (AllowlistEmailDomains allowed)) _ (Left email) = emailDomain email `elem` allowed +verify _ (Just (AllowlistPhonePrefixes allowed)) (Right phone) = any (`Text.isPrefixOf` fromPhone phone) allowed verify Nothing _ (Left _) = True verify _ Nothing (Right _) = True From cd42e8d944eddcf75dbe49683e4ff67b7a61334c Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Fri, 10 Feb 2023 07:35:57 +0100 Subject: [PATCH 10/11] Fixup --- .../developer/reference/user/activation.md | 2 +- libs/wire-api/src/Wire/API/Error/Brig.hs | 4 +-- libs/wire-api/src/Wire/API/User.hs | 4 +-- services/brig/brig.cabal | 2 +- services/brig/src/Brig/API/Auth.hs | 2 +- services/brig/src/Brig/API/Error.hs | 4 +-- services/brig/src/Brig/API/Handler.hs | 26 +++++++++---------- services/brig/src/Brig/API/Public.hs | 10 +++---- .../src/Brig/{Whitelist.hs => Allowlists.hs} | 4 +-- services/brig/src/Brig/Options.hs | 2 +- 10 files changed, 30 insertions(+), 30 deletions(-) rename services/brig/src/Brig/{Whitelist.hs => Allowlists.hs} (95%) diff --git a/docs/src/developer/reference/user/activation.md b/docs/src/developer/reference/user/activation.md index 8a2a612a242..031c4dc39fe 100644 --- a/docs/src/developer/reference/user/activation.md +++ b/docs/src/developer/reference/user/activation.md @@ -135,7 +135,7 @@ X-Zeta-Code: 123456 ``` ## Phone/email whitelist -(RefActivationWhitelist)= +(RefActivationAllowlist)= The backend can be configured to only allow specific phone number prefixes and email address domains to register. The following options have to be set in `brig.yaml`: diff --git a/libs/wire-api/src/Wire/API/Error/Brig.hs b/libs/wire-api/src/Wire/API/Error/Brig.hs index 7b1b3370360..949d3c45725 100644 --- a/libs/wire-api/src/Wire/API/Error/Brig.hs +++ b/libs/wire-api/src/Wire/API/Error/Brig.hs @@ -43,7 +43,7 @@ data BrigError | HandleNotFound | UserCreationRestricted | BlacklistedPhone - | WhitelistError + | AllowlistError | InvalidInvitationCode | MissingIdentity | BlacklistedEmail @@ -135,7 +135,7 @@ type instance MapError 'MLSDuplicatePublicKey = 'StaticError 400 "mls-duplicate- type instance MapError 'BlacklistedPhone = 'StaticError 403 "blacklisted-phone" "The given phone number has been blacklisted due to suspected abuse or a complaint" -type instance MapError 'WhitelistError = 'StaticError 403 "unauthorized" "Unauthorized e-mail address or phone number." +type instance MapError 'AllowlistError = 'StaticError 403 "unauthorized" "Unauthorized e-mail address or phone number." type instance MapError 'InvalidInvitationCode = 'StaticError 400 "invalid-invitation-code" "Invalid invitation code." diff --git a/libs/wire-api/src/Wire/API/User.hs b/libs/wire-api/src/Wire/API/User.hs index 1e41a89c9db..b25311eb936 100644 --- a/libs/wire-api/src/Wire/API/User.hs +++ b/libs/wire-api/src/Wire/API/User.hs @@ -560,7 +560,7 @@ instance Arbitrary NewUserPublic where arbitrary = arbitrary `QC.suchThatMap` (rightMay . validateNewUserPublic) data RegisterError - = RegisterErrorWhitelistError + = RegisterErrorAllowlistError | RegisterErrorInvalidInvitationCode | RegisterErrorMissingIdentity | RegisterErrorUserKeyExists @@ -578,7 +578,7 @@ data RegisterError instance GSOP.Generic RegisterError type RegisterErrorResponses = - '[ ErrorResponse 'WhitelistError, + '[ ErrorResponse 'AllowlistError, ErrorResponse 'InvalidInvitationCode, ErrorResponse 'MissingIdentity, ErrorResponse 'UserKeyExists, diff --git a/services/brig/brig.cabal b/services/brig/brig.cabal index 5acda036e34..fea62758493 100644 --- a/services/brig/brig.cabal +++ b/services/brig/brig.cabal @@ -17,6 +17,7 @@ extra-source-files: library -- cabal-fmt: expand src exposed-modules: + Brig.Allowlists Brig.API Brig.API.Auth Brig.API.Client @@ -130,7 +131,6 @@ library Brig.User.Search.TeamUserSearch Brig.User.Template Brig.Version - Brig.Whitelist Brig.ZAuth other-modules: Paths_brig diff --git a/services/brig/src/Brig/API/Auth.hs b/services/brig/src/Brig/API/Auth.hs index b89733053e3..7a9fd86b67e 100644 --- a/services/brig/src/Brig/API/Auth.hs +++ b/services/brig/src/Brig/API/Auth.hs @@ -74,7 +74,7 @@ access mcid t mt = sendLoginCode :: SendLoginCode -> Handler r LoginCodeTimeout sendLoginCode (SendLoginCode phone call force) = do - checkWhitelist (Right phone) + checkAllowlist (Right phone) c <- wrapClientE (Auth.sendLoginCode phone call force) !>> sendLoginCodeError pure $ LoginCodeTimeout (pendingLoginTimeout c) diff --git a/services/brig/src/Brig/API/Error.hs b/services/brig/src/Brig/API/Error.hs index 0f76c11ac26..22290a120d6 100644 --- a/services/brig/src/Brig/API/Error.hs +++ b/services/brig/src/Brig/API/Error.hs @@ -295,8 +295,8 @@ activationCodeNotFound = invalidActivationCode "Activation key/code not found or deletionCodePending :: Wai.Error deletionCodePending = Wai.mkError status403 "pending-delete" "A verification code for account deletion is still pending." -whitelistError :: Wai.Error -whitelistError = Wai.mkError status403 "unauthorized" "Unauthorized e-mail address or phone number." +allowlistError :: Wai.Error +allowlistError = Wai.mkError status403 "unauthorized" "Unauthorized e-mail address or phone number." blacklistedEmail :: Wai.Error blacklistedEmail = diff --git a/services/brig/src/Brig/API/Handler.hs b/services/brig/src/Brig/API/Handler.hs index 8c32fb01c5c..8f69ef1cc64 100644 --- a/services/brig/src/Brig/API/Handler.hs +++ b/services/brig/src/Brig/API/Handler.hs @@ -24,9 +24,9 @@ module Brig.API.Handler -- * Utilities JSON, parseJsonBody, - checkWhitelist, - checkWhitelistWithError, - isWhiteListed, + checkAllowlist, + checkAllowlistWithError, + isAllowlisted, UserNotAllowedToJoinTeam (..), ) where @@ -34,12 +34,12 @@ where import Bilge (RequestId (..)) import Brig.API.Error import qualified Brig.AWS as AWS +import qualified Brig.Allowlists as Allowlists import Brig.App import Brig.CanonicalInterpreter (BrigCanonicalEffects, runBrigToIO) import Brig.Email (Email) import Brig.Options (setAllowlistEmailDomains, setAllowlistPhonePrefixes) import Brig.Phone (Phone, PhoneException (..)) -import qualified Brig.Whitelist as Whitelist import Control.Error import Control.Exception (throwIO) import Control.Lens (set, view) @@ -167,16 +167,16 @@ type JSON = Media "application" "json" parseJsonBody :: (FromJSON a, MonadIO m) => JsonRequest a -> ExceptT Error m a parseJsonBody req = parseBody req !>> StdError . badRequest --- | If a whitelist is configured, consult it, otherwise a no-op. {#RefActivationWhitelist} -checkWhitelist :: Either Email Phone -> (Handler r) () -checkWhitelist = wrapHttpClientE . checkWhitelistWithError (StdError whitelistError) +-- | If an Allowlist is configured, consult it, otherwise a no-op. {#RefActivationAllowlist} +checkAllowlist :: Either Email Phone -> (Handler r) () +checkAllowlist = wrapHttpClientE . checkAllowlistWithError (StdError allowlistError) -checkWhitelistWithError :: (MonadReader Env m, MonadError e m) => e -> Either Email Phone -> m () -checkWhitelistWithError e key = do - ok <- isWhiteListed key +checkAllowlistWithError :: (MonadReader Env m, MonadError e m) => e -> Either Email Phone -> m () +checkAllowlistWithError e key = do + ok <- isAllowlisted key unless ok (throwError e) -isWhiteListed :: (MonadReader Env m) => Either Email Phone -> m Bool -isWhiteListed key = do +isAllowlisted :: (MonadReader Env m) => Either Email Phone -> m Bool +isAllowlisted key = do env <- view settings - pure $ Whitelist.verify (setAllowlistEmailDomains env) (setAllowlistPhonePrefixes env) key + pure $ Allowlists.verify (setAllowlistEmailDomains env) (setAllowlistPhonePrefixes env) key diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index c62128ab367..84472f42d00 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -129,7 +129,7 @@ import Wire.API.SwaggerHelper (cleanupSwagger) import Wire.API.SystemSettings import qualified Wire.API.Team as Public import Wire.API.Team.LegalHold (LegalholdProtectee (..)) -import Wire.API.User (RegisterError (RegisterErrorWhitelistError)) +import Wire.API.User (RegisterError (RegisterErrorAllowlistError)) import qualified Wire.API.User as Public import qualified Wire.API.User.Activation as Public import qualified Wire.API.User.Auth as Public @@ -601,8 +601,8 @@ createUser :: (Handler r) (Either Public.RegisterError Public.RegisterSuccess) createUser (Public.NewUserPublic new) = lift . runExceptT $ do API.checkRestrictedUserCreation new - for_ (Public.newUserEmail new) $ mapExceptT wrapHttp . checkWhitelistWithError RegisterErrorWhitelistError . Left - for_ (Public.newUserPhone new) $ mapExceptT wrapHttp . checkWhitelistWithError RegisterErrorWhitelistError . Right + for_ (Public.newUserEmail new) $ mapExceptT wrapHttp . checkAllowlistWithError RegisterErrorAllowlistError . Left + for_ (Public.newUserPhone new) $ mapExceptT wrapHttp . checkAllowlistWithError RegisterErrorAllowlistError . Right result <- API.createUser new let acc = createdAccount result @@ -851,7 +851,7 @@ beginPasswordReset :: Public.NewPasswordReset -> (Handler r) () beginPasswordReset (Public.NewPasswordReset target) = do - checkWhitelist target + checkAllowlist target (u, pair) <- API.beginPasswordReset target !>> pwResetError loc <- lift $ wrapClient $ API.lookupLocale u lift $ case target of @@ -878,7 +878,7 @@ sendActivationCode :: (Handler r) () sendActivationCode Public.SendActivationCode {..} = do either customerExtensionCheckBlockedDomains (const $ pure ()) saUserKey - checkWhitelist saUserKey + checkAllowlist saUserKey API.sendActivationCode saUserKey saLocale saCall !>> sendActCodeError -- | If the user presents an email address from a blocked domain, throw an error. diff --git a/services/brig/src/Brig/Whitelist.hs b/services/brig/src/Brig/Allowlists.hs similarity index 95% rename from services/brig/src/Brig/Whitelist.hs rename to services/brig/src/Brig/Allowlists.hs index fe110eaec23..5b33b853a76 100644 --- a/services/brig/src/Brig/Whitelist.hs +++ b/services/brig/src/Brig/Allowlists.hs @@ -15,10 +15,10 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . --- | > docs/reference/user/activation.md {#RefActivationWhitelist} +-- | > docs/reference/user/activation.md {#RefActivationAllowlist} -- -- Email/phone whitelist. -module Brig.Whitelist +module Brig.Allowlists ( AllowlistEmailDomains (..), AllowlistPhonePrefixes (..), verify, diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index d7030ecc18f..4caa8c8c78e 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -21,10 +21,10 @@ module Brig.Options where +import Brig.Allowlists (AllowlistEmailDomains (..), AllowlistPhonePrefixes (..)) import Brig.Queue.Types (Queue (..)) import Brig.SMTP (SMTPConnType (..)) import Brig.User.Auth.Cookie.Limit -import Brig.Whitelist (AllowlistEmailDomains (..), AllowlistPhonePrefixes (..)) import qualified Brig.ZAuth as ZAuth import Control.Applicative import qualified Control.Lens as Lens From 8c1626bdbb4bd4a47ab1e2121c04b0a69bf25301 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Fri, 10 Feb 2023 07:44:44 +0100 Subject: [PATCH 11/11] Unrelated, but hey! --- services/gundeck/src/Gundeck/Push.hs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/services/gundeck/src/Gundeck/Push.hs b/services/gundeck/src/Gundeck/Push.hs index f863ff57a03..225cd089349 100644 --- a/services/gundeck/src/Gundeck/Push.hs +++ b/services/gundeck/src/Gundeck/Push.hs @@ -299,18 +299,21 @@ compilePushResps notifIdMap (Map.fromList -> deliveries) = -- | Is 'PushTarget' the origin of the 'Push', or is missing in a non-empty whitelist? (Whitelists -- reside both in 'Push' itself and in each 'Recipient'). shouldActuallyPush :: Push -> Recipient -> Presence -> Bool -shouldActuallyPush psh rcp pres = not isOrigin && okByPushWhitelist && okByRecipientWhitelist +shouldActuallyPush psh rcp pres = not isOrigin && okByPushAllowlist && okByRecipientAllowlist where isOrigin = psh ^. pushOrigin == Just (userId pres) && psh ^. pushOriginConnection == Just (connId pres) - okByPushWhitelist = not whitelistExists || isWhitelisted + + okByPushAllowlist :: Bool + okByPushAllowlist = not allowlistExists || isAllowlisted where - whitelist = psh ^. pushConnections - whitelistExists = not $ Set.null whitelist - isWhitelisted = connId pres `Set.member` whitelist - okByRecipientWhitelist :: Bool - okByRecipientWhitelist = + allowlist = psh ^. pushConnections + allowlistExists = not $ Set.null allowlist + isAllowlisted = connId pres `Set.member` allowlist + + okByRecipientAllowlist :: Bool + okByRecipientAllowlist = case (rcp ^. recipientClients, clientId pres) of (RecipientClientsSome cs, Just c) -> c `elem` cs _ -> True