Skip to content

Commit

Permalink
Merge pull request #1202 from wireapp/release_2020_09_04
Browse files Browse the repository at this point in the history
  • Loading branch information
tiago-loureiro authored Sep 10, 2020
2 parents 4cb3364 + c2a07f7 commit 37eaab2
Show file tree
Hide file tree
Showing 282 changed files with 4,806 additions and 2,948 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# 2020-09-04

## Release Notes

## Bug Fixes

* Fixed logic related to ephemeral users (#1197)

## New Features

* SFT servers now exposed over /calls/config/v2 (#1177)
* First federation endpoint (#1188)

## Internal changes

* ormolu upgrade to 0.1.2.0 and formatting (#1145, #1185, #1186)
* handy cqlsh make target to manually poke at the database (#1170)
* spar cleanup
* brig user name during scim user parsing (#1195)
* invitation refactor (#1196)
* SCIM users are never ephemeral (#1198)


# 2020-07-29

## Release Notes
Expand Down
1 change: 1 addition & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Please check Wire's [global SECURITY.md](https://github.com/wireapp/wire/blob/master/SECURITY.md).
7 changes: 3 additions & 4 deletions docs/reference/user/registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,13 @@ We need an option to block 1, 2, 5 on-prem; 3, 4 should remain available (no blo
* Allow team members to register (via email/phone or SSO)
* Allow ephemeral users

During registration, we can take advantage of [NewUserOrigin](https://github.com/wireapp/wire-server/blob/a89b9cd818997e7837e5d0938ecfd90cf8dd9e52/libs/wire-api/src/Wire/API/User.hs#L625); we're particularly interested in `NewUserOriginTeamUser` --> only `NewTeamMember` or `NewTeamMemberSSO` should be accepted. In case this is a `Nothing`, we need to check if the user expires, i.e., `newUserExpiresIn` must be a `Just`.
During registration, we can take advantage of [NewUserOrigin](https://github.com/wireapp/wire-server/blob/a89b9cd818997e7837e5d0938ecfd90cf8dd9e52/libs/wire-api/src/Wire/API/User.hs#L625); we're particularly interested in `NewUserOriginTeamUser` --> only `NewTeamMember` or `NewTeamMemberSSO` should be accepted. In case this is a `Nothing`, we need to check if the user expires, i.e., if the user has no identity (and thus `Ephemeral`).

So `/register` should only succeed iff at least one of these conditions is true:

```
newUserTeam == (Just (NewTeamMember _)) OR
newUserTeam == (Just (NewTeamMemberSSO _)) OR
newUserExpiresIn == (Just _)
import Brig.Types.User
isNewUserTeamMember || isNewUserEphemeral
```

The rest of the unauthorized end-points is safe:
Expand Down
4 changes: 2 additions & 2 deletions libs/api-bot/src/Network/Wire/Bot/Cache.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ empty :: IO Cache
empty = Cache <$> newIORef []

get :: (MonadIO m, HasCallStack) => Cache -> m CachedUser
get c = liftIO $ atomicModifyIORef (cache c) $ \u ->
get c = liftIO . atomicModifyIORef (cache c) $ \u ->
case u of
[] ->
error
Expand All @@ -71,7 +71,7 @@ get c = liftIO $ atomicModifyIORef (cache c) $ \u ->
(x : xs) -> (xs, x)

put :: MonadIO m => Cache -> CachedUser -> m ()
put c a = liftIO $ atomicModifyIORef (cache c) $ \u -> (a : u, ())
put c a = liftIO . atomicModifyIORef (cache c) $ \u -> (a : u, ())

toUser :: HasCallStack => Logger -> [CachedUser] -> [LText] -> IO [CachedUser]
toUser _ acc [i, e, p] = do
Expand Down
6 changes: 3 additions & 3 deletions libs/api-bot/src/Network/Wire/Bot/Crypto.hs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ decryptSymmetric _ (SymmetricKeys ekey mkey) msg = liftIO $ do
let (dgst, ciphertext) = BS.splitAt 32 msg
sha256 <- requireMaybe (digestFromByteString dgst) "Bad MAC"
let mac = hmac (toByteString' mkey) ciphertext :: HMAC SHA256
unless (HMAC sha256 == mac)
$ throwM
$ RequirementFailed "Bad MAC"
unless (HMAC sha256 == mac) $
throwM $
RequirementFailed "Bad MAC"
let (iv, dat) = BS.splitAt 16 ciphertext
return $ unpadPKCS7 $ cbcDecrypt aes (aesIV iv) dat

Expand Down
2 changes: 1 addition & 1 deletion libs/api-bot/src/Network/Wire/Bot/Crypto/Glue.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ deleteBox :: UserId -> Maybe Text -> IO ()
deleteBox uid label = do
dir <- getBoxDir uid label
removePathForcibly dir -- using "forcibly" so that it wouldn't fail
-- if the directory doesn't exist
-- if the directory doesn't exist

genPrekeys :: Box -> Word16 -> IO [C.Prekey]
genPrekeys box n = mapM (genPrekey box) [1 .. n - 1]
Expand Down
98 changes: 50 additions & 48 deletions libs/api-bot/src/Network/Wire/Bot/Monad.hs
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,16 @@ initMetrics = do
return m
where
counters =
Metrics.assertionsTotal
: Metrics.assertionsFailed
: Metrics.exceptionsTotal
: Metrics.botsCreatedNew
: Metrics.botsCreatedCached
: Metrics.eventsTotalRcvd
: Metrics.eventsTotalAckd
: Metrics.eventsTotalIgnd
: Metrics.eventsTotalMssd
: concatMap etc [(minBound :: EventType) ..]
Metrics.assertionsTotal :
Metrics.assertionsFailed :
Metrics.exceptionsTotal :
Metrics.botsCreatedNew :
Metrics.botsCreatedCached :
Metrics.eventsTotalRcvd :
Metrics.eventsTotalAckd :
Metrics.eventsTotalIgnd :
Metrics.eventsTotalMssd :
concatMap etc [(minBound :: EventType) ..]
etc t =
[ Metrics.eventTypeRcvd t,
Metrics.eventTypeAckd t,
Expand Down Expand Up @@ -562,9 +562,9 @@ assertEqual a b m =

assertTrue :: (HasCallStack, MonadBotNet m) => Bool -> Text -> m ()
assertTrue b m =
whenAsserts
$ unless b
$ assertFailure m -- the 'unless' is hidden under 'whenAsserts'
whenAsserts $
unless b $
assertFailure m -- the 'unless' is hidden under 'whenAsserts'
-- because we don't want 'b' to be evaluated
-- when asserts are disabled

Expand Down Expand Up @@ -615,7 +615,7 @@ scheduleAssert bot typ f out = whenAsserts $ do
writeTQueue (botAsserts bot) (EventAssertion typ t f out callStack)
writeTVar (botAssertCount bot) (n + 1)
return True
unless r $ liftBotNet $ do
unless r . liftBotNet $ do
incrAssertFailed
runBotSession bot . log Error . msg $
"Too many event assertions. Dropped: " <> eventTypeText typ
Expand Down Expand Up @@ -698,7 +698,7 @@ mkBot tag user pw = do
return bot

connectPush :: Bot -> BotNetEnv -> IO (Async ())
connectPush bot e = runBotNet e $ runBotSession bot $ do
connectPush bot e = runBotNet e . runBotSession bot $ do
log Info $ msg (val "Establishing push channel")
awaitNotifications (consume bot e)

Expand All @@ -725,14 +725,14 @@ heartbeat bot e = forever $ do
let l = botNetLogger e
-- Refresh the auth token, if necessary
(auth, expiry) <- readIORef $ botAuth bot
when (now > expiry)
$ void . forkIO . runBotNet e . runBotSession bot
$ do
log Debug $ msg (val "Refreshing auth token")
refreshAuth auth
>>= maybe
(log Error $ msg (val "Failed to refresh auth token"))
setAuth
when (now > expiry) $
void . forkIO . runBotNet e . runBotSession bot $
do
log Debug $ msg (val "Refreshing auth token")
refreshAuth auth
>>= maybe
(log Error $ msg (val "Failed to refresh auth token"))
setAuth
-- Event & assertion maintenance
when (botNetAssert e) $ do
-- Remove old events from the inbox
Expand All @@ -742,17 +742,18 @@ heartbeat bot e = forever $ do
msg ("Event Timeout: " <> showEventType evt)
-- Check if the event inbox is full and if so, log a warning
size <- fst <$> readTVarIO (botEvents bot)
when (size == botMaxEvents (botSettings bot))
$ botLog l bot Warn
$ msg (val "Event inbox full!")
when (size == botMaxEvents (botSettings bot)) $
botLog l bot Warn $
msg (val "Event inbox full!")
-- Remove old assertions from the backlog
asserts <- atomically $ gcBacklog bot now
forM_ asserts $ \(EventAssertion typ _ _ out stack) -> do
for_ out $ liftIO . atomically . flip tryPutTMVar Nothing
botLog l bot Warn $ msg $
"Assertion Timeout: " <> eventTypeText typ
<> "\nAssertion was created at: "
<> pack (prettyCallStack stack)
botLog l bot Warn $
msg $
"Assertion Timeout: " <> eventTypeText typ
<> "\nAssertion was created at: "
<> pack (prettyCallStack stack)
-- Re-establish the push connection, if it died
push <- maybe (return Nothing) poll =<< readIORef (botPushThread bot)
case push of
Expand Down Expand Up @@ -922,24 +923,25 @@ incrEventsMssd b e =
HashMap.insertWith (+) (Metrics.eventTypeMssd e) 1

transferBotMetrics :: MonadBotNet m => Bot -> m ()
transferBotMetrics b = getMetrics >>= \m -> liftIO $ do
-- Obtain current values
l@[rcvd, ackd, ignd, mssd] <- atomically $ do
rcvd <- readTVar $ botEventsRcvd (botMetrics b)
ackd <- readTVar $ botEventsAckd (botMetrics b)
ignd <- readTVar $ botEventsIgnd (botMetrics b)
mssd <- readTVar $ botEventsMssd (botMetrics b)
return [rcvd, ackd, ignd, mssd]
-- Update per event type counters
let add (p, n) = Metrics.counterAdd n p m
mapM_ add (concatMap HashMap.toList l)
-- Update Totals
add (Metrics.eventsTotalRcvd, sum rcvd)
add (Metrics.eventsTotalAckd, sum ackd)
add (Metrics.eventsTotalIgnd, sum ignd)
let s = sum mssd
add (Metrics.eventsTotalMssd, s)
add (Metrics.assertionsFailed, s)
transferBotMetrics b =
getMetrics >>= \m -> liftIO $ do
-- Obtain current values
l@[rcvd, ackd, ignd, mssd] <- atomically $ do
rcvd <- readTVar $ botEventsRcvd (botMetrics b)
ackd <- readTVar $ botEventsAckd (botMetrics b)
ignd <- readTVar $ botEventsIgnd (botMetrics b)
mssd <- readTVar $ botEventsMssd (botMetrics b)
return [rcvd, ackd, ignd, mssd]
-- Update per event type counters
let add (p, n) = Metrics.counterAdd n p m
mapM_ add (concatMap HashMap.toList l)
-- Update Totals
add (Metrics.eventsTotalRcvd, sum rcvd)
add (Metrics.eventsTotalAckd, sum ackd)
add (Metrics.eventsTotalIgnd, sum ignd)
let s = sum mssd
add (Metrics.eventsTotalMssd, s)
add (Metrics.assertionsFailed, s)

-------------------------------------------------------------------------------
-- Logging
Expand Down
8 changes: 5 additions & 3 deletions libs/bilge/src/Bilge/Assert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ io <!! aa = do
r <- io `catch` printErr
let results = map ($ r) (execWriter . _assertions $ aa)
let failures = filter (isJust . snd) $ zip [1 ..] results
unless (null failures) $ error . concat $
title "Assertions failed:\n" : intersperse "\n" (map msg failures)
++ ["\n\nResponse was:\n\n" ++ show r]
unless (null failures) $
error . concat $
title "Assertions failed:\n" :
intersperse "\n" (map msg failures)
++ ["\n\nResponse was:\n\n" ++ show r]
return r
where
msg :: (Int, Maybe String) -> String
Expand Down
2 changes: 1 addition & 1 deletion libs/bilge/src/Bilge/IO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ instance MonadBaseControl IO (HttpT IO) where

instance MonadUnliftIO m => MonadUnliftIO (HttpT m) where
withRunInIO inner =
HttpT $ ReaderT $ \r ->
HttpT . ReaderT $ \r ->
withRunInIO $ \run ->
inner (run . runHttpT r)

Expand Down
6 changes: 3 additions & 3 deletions libs/bilge/src/Bilge/RPC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ statusCheck ::
Response (Maybe LByteString) ->
m ()
statusCheck c f r =
unless (statusCode r == c)
$ throwError
$ f ("unexpected status code: " <> pack (show $ statusCode r))
unless (statusCode r == c) $
throwError $
f ("unexpected status code: " <> pack (show $ statusCode r))

parseResponse ::
(Exception e, MonadThrow m, Monad m, FromJSON a) =>
Expand Down
12 changes: 6 additions & 6 deletions libs/bilge/src/Bilge/Response.hs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ getCookieValue :: ByteString -> Response a -> Maybe ByteString
getCookieValue cookieName resp =
resp
^? to responseHeaders
. traversed -- Over each header
. filtered ((== "Set-Cookie") . fst) -- Select the cookie headers by name
. _2 -- Select Set-Cookie values
. to parseSetCookie
. filtered ((== cookieName) . setCookieName) -- Select only the cookie we want
. to setCookieValue -- extract the cookie value
. traversed -- Over each header
. filtered ((== "Set-Cookie") . fst) -- Select the cookie headers by name
. _2 -- Select Set-Cookie values
. to parseSetCookie
. filtered ((== cookieName) . setCookieName) -- Select only the cookie we want
. to setCookieValue -- extract the cookie value

type ResponseLBS = Response (Maybe LByteString)

Expand Down
6 changes: 3 additions & 3 deletions libs/brig-types/brig-types.cabal
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
cabal-version: 1.12

-- This file has been generated from package.yaml by hpack version 0.31.2.
-- This file has been generated from package.yaml by hpack version 0.33.0.
--
-- see: https://github.com/sol/hpack
--
-- hash: 7497d04521f12339e2a8f5537dacf242839dea9034f69e67f0a254b1548cadd9
-- hash: fe16e52e870cb548573366fe9192319004e52c3e4d2ece172df69e408cbe391b

name: brig-types
version: 1.35.0
Expand All @@ -21,6 +21,7 @@ library
exposed-modules:
Brig.Types
Brig.Types.Activation
Brig.Types.Calling
Brig.Types.Client
Brig.Types.Client.Prekey
Brig.Types.Code
Expand All @@ -37,7 +38,6 @@ library
Brig.Types.Team.Invitation
Brig.Types.Team.LegalHold
Brig.Types.Test.Arbitrary
Brig.Types.TURN
Brig.Types.User
Brig.Types.User.Auth
other-modules:
Expand Down
2 changes: 1 addition & 1 deletion libs/brig-types/src/Brig/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ module Brig.Types
where

import Brig.Types.Activation as M
import Brig.Types.Calling as M
import Brig.Types.Client as M
import Brig.Types.Connection as M
import Brig.Types.Properties as M
import Brig.Types.Search as M
import Brig.Types.TURN as M
import Brig.Types.Team as M
import Brig.Types.User as M
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Brig.Types.TURN
module Brig.Types.Calling
( -- * re-exports
RTCConfiguration,
rtcConfiguration,
Expand Down Expand Up @@ -50,4 +50,4 @@ module Brig.Types.TURN
)
where

import Wire.API.Call.TURN
import Wire.API.Call.Config
2 changes: 2 additions & 0 deletions libs/brig-types/src/Brig/Types/User.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ module Brig.Types.User
newUserEmail,
newUserPhone,
newUserSSOId,
isNewUserEphemeral,
isNewUserTeamMember,
InvitationCode (..),
BindingNewTeamUser (..),
NewTeamUser (..),
Expand Down
2 changes: 1 addition & 1 deletion libs/brig-types/test/unit/Test/Brig/Roundtrip.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Data.Aeson (FromJSON, ToJSON, parseJSON, toJSON)
import Data.Aeson.Types (parseEither)
import Imports
import Test.Tasty (TestTree)
import Test.Tasty.QuickCheck ((===), Arbitrary, counterexample, testProperty)
import Test.Tasty.QuickCheck (Arbitrary, counterexample, testProperty, (===))
import Type.Reflection (typeRep)

testRoundTrip ::
Expand Down
4 changes: 2 additions & 2 deletions libs/cassandra-util/src/Cassandra/Exec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ where
import Cassandra.CQL (Consistency, R)
import Control.Monad.Catch
import Data.Conduit
-- Things we just import and re-export.
import Database.CQL.IO as C (BatchM, Client, ClientState, MonadClient, Page (..), PrepQuery, Row, addPrepQuery, addQuery, adjustConsistency, adjustResponseTimeout, adjustSendTimeout, batch, emptyPage, init, liftClient, localState, paginate, prepared, query, query1, queryString, retry, runClient, schema, setConsistency, setSerialConsistency, setType, shutdown, trans, write)
-- We only use these locally.
import Database.CQL.IO (RetrySettings, RunQ, defRetrySettings, eagerRetrySettings)
-- Things we just import and re-export.
import Database.CQL.IO as C (BatchM, Client, ClientState, MonadClient, Page (..), PrepQuery, Row, addPrepQuery, addQuery, adjustConsistency, adjustResponseTimeout, adjustSendTimeout, batch, emptyPage, init, liftClient, localState, paginate, prepared, query, query1, queryString, retry, runClient, schema, setConsistency, setSerialConsistency, setType, shutdown, trans, write)
import Database.CQL.Protocol (Error, QueryParams (QueryParams), Tuple)
import Imports hiding (init)

Expand Down
Loading

0 comments on commit 37eaab2

Please sign in to comment.