Skip to content

Commit 38d3398

Browse files
authored
Improve usage of http-manager (fixes for fingerprint verification) (#3825)
* [fix] reuse manager * [feat] bring back no reuse of the manager for * [fix] fresh manager for each bot
1 parent 6a77ffa commit 38d3398

File tree

11 files changed

+57
-22
lines changed

11 files changed

+57
-22
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- reuse the http manager wherever possible
2+
- don't reuse the http manager in legalhold scenarios
3+
- don't concurrently modify the ssl context in such ways that
4+
it can create race conditions

libs/ssl-util/src/Ssl/Util.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,18 @@ verifyRsaFingerprint d = verifyFingerprint $ \pk ->
182182

183183
-- | this is used as a 'OpenSSL.Session.vpCallback' in 'Brig.App.initExtGetManager'
184184
-- and 'Galley.Env.initExtEnv'
185-
extEnvCallback :: [Fingerprint Rsa] -> X509StoreCtx -> IO Bool
185+
extEnvCallback :: IORef [Fingerprint Rsa] -> X509StoreCtx -> IO Bool
186186
extEnvCallback fingerprints store = do
187187
Just sha <- getDigestByName "SHA256"
188188
cert <- getStoreCtxCert store
189189
pk <- getPublicKey cert
190+
fprs <- readIORef fingerprints
190191
case toPublicKey @RSAPubKey pk of
191192
Nothing -> pure False
192193
Just k -> do
193194
fp <- rsaFingerprint sha k
194195
-- find at least one matching fingerprint to continue
195-
if not (any (constEqBytes fp . fingerprintBytes) fingerprints)
196+
if not (any (constEqBytes fp . fingerprintBytes) fprs)
196197
then pure False
197198
else do
198199
-- Check if the certificate is self-signed.

services/brig/src/Brig/App.hs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module Brig.App
4646
httpManager,
4747
http2Manager,
4848
extGetManager,
49+
initExtGetManager,
4950
nexmoCreds,
5051
twilioCreds,
5152
settings,
@@ -71,7 +72,7 @@ module Brig.App
7172

7273
-- * Crutches that should be removed once Brig has been completely
7374

74-
-- * transitioned to Polysemy
75+
-- transitioned to Polysemy
7576
wrapClient,
7677
wrapClientE,
7778
wrapClientM,
@@ -172,7 +173,7 @@ data Env = Env
172173
_templateBranding :: TemplateBranding,
173174
_httpManager :: Manager,
174175
_http2Manager :: Http2Manager,
175-
_extGetManager :: [Fingerprint Rsa] -> IO Manager,
176+
_extGetManager :: (Manager, IORef [Fingerprint Rsa]),
176177
_settings :: Settings,
177178
_nexmoCreds :: Nexmo.Credentials,
178179
_twilioCreds :: Twilio.Credentials,
@@ -246,6 +247,9 @@ newEnv o = do
246247
pure Nothing
247248
kpLock <- newMVar ()
248249
rabbitChan <- traverse (Q.mkRabbitMqChannelMVar lgr) o.rabbitmq
250+
fprVar <- newIORef []
251+
extMgr <- initExtGetManager fprVar
252+
249253
pure $!
250254
Env
251255
{ _cargohold = mkEndpoint $ Opt.cargohold o,
@@ -267,7 +271,7 @@ newEnv o = do
267271
_templateBranding = branding,
268272
_httpManager = mgr,
269273
_http2Manager = h2Mgr,
270-
_extGetManager = initExtGetManager,
274+
_extGetManager = (extMgr, fprVar),
271275
_settings = sett,
272276
_nexmoCreds = nxm,
273277
_twilioCreds = twl,
@@ -359,8 +363,8 @@ initHttp2Manager = do
359363
-- faster. So, we reuse the context.
360364

361365
-- TODO: somewhat duplicates Galley.App.initExtEnv
362-
initExtGetManager :: [Fingerprint Rsa] -> IO Manager
363-
initExtGetManager fingerprints = do
366+
initExtGetManager :: IORef [Fingerprint Rsa] -> IO Manager
367+
initExtGetManager fprVar = do
364368
ctx <- SSL.context
365369
SSL.contextAddOption ctx SSL_OP_NO_SSLv2
366370
SSL.contextAddOption ctx SSL_OP_NO_SSLv3
@@ -369,8 +373,8 @@ initExtGetManager fingerprints = do
369373
ctx
370374
SSL.VerifyPeer
371375
{ vpFailIfNoPeerCert = True,
372-
vpClientOnce = False,
373-
vpCallback = Just \_b -> extEnvCallback fingerprints
376+
vpClientOnce = True,
377+
vpCallback = Just \_b -> extEnvCallback fprVar
374378
}
375379

376380
SSL.contextSetDefaultVerifyPaths ctx

services/brig/src/Brig/Provider/RPC.hs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import Brig.App
3535
import Brig.Provider.DB (ServiceConn (..))
3636
import Brig.RPC
3737
import Control.Error
38-
import Control.Lens (set, view, (^.))
38+
import Control.Lens (set, (^.))
3939
import Control.Monad.Catch
4040
import Control.Retry (recovering)
4141
import Data.Aeson
@@ -71,8 +71,9 @@ data ServiceError
7171
createBot :: ServiceConn -> NewBotRequest -> ExceptT ServiceError (AppT r) NewBotResponse
7272
createBot scon new = do
7373
let fprs = toList (sconFingerprints scon)
74-
manF <- view extGetManager
75-
man <- liftIO $ manF fprs
74+
-- fresh http manager
75+
man <- liftIO do
76+
initExtGetManager =<< newIORef fprs
7677
extHandleAll onExc $ do
7778
let req = reqBuilder Http.defaultRequest
7879
rs <- lift $

services/galley/src/Galley/App.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,11 @@ createEnv m o l = do
158158
mgr <- initHttpManager o
159159
h2mgr <- initHttp2Manager
160160
codeURIcfg <- validateOptions o
161+
fprVar <- newIORef []
162+
extEnv <- initExtEnv fprVar
161163
Env (RequestId "N/A") m o l mgr h2mgr (o ^. O.federator) (o ^. O.brig) cass
162164
<$> Q.new 16000
163-
<*> pure initExtEnv
165+
<*> pure (extEnv, fprVar)
164166
<*> maybe (pure Nothing) (fmap Just . Aws.mkEnv l mgr) (o ^. journal)
165167
<*> loadAllMLSKeys (fold (o ^. settings . mlsPrivateKeyPaths))
166168
<*> traverse (mkRabbitMqChannelMVar l) (o ^. rabbitmq)

services/galley/src/Galley/Cassandra/LegalHold.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ interpretLegalHoldStoreToCassandra lh = interpret $ \case
7373
SetTeamLegalholdWhitelisted tid -> embedClient $ setTeamLegalholdWhitelisted tid
7474
UnsetTeamLegalholdWhitelisted tid -> embedClient $ unsetTeamLegalholdWhitelisted tid
7575
IsTeamLegalholdWhitelisted tid -> embedClient $ isTeamLegalholdWhitelisted lh tid
76+
-- FUTUREWORK: should this action be part of a separate effect?
77+
MakeVerifiedRequestFreshManager fpr url r ->
78+
embedApp $ makeVerifiedRequestFreshManager fpr url r
7679
MakeVerifiedRequest fpr url r ->
7780
embedApp $ makeVerifiedRequest fpr url r
7881
ValidateServiceKey sk -> embed @IO $ validateServiceKey sk

services/galley/src/Galley/Effects/LegalHoldStore.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ module Galley.Effects.LegalHoldStore
3636

3737
-- * Intra actions
3838
makeVerifiedRequest,
39+
makeVerifiedRequestFreshManager,
3940
)
4041
where
4142

@@ -61,7 +62,12 @@ data LegalHoldStore m a where
6162
SetTeamLegalholdWhitelisted :: TeamId -> LegalHoldStore m ()
6263
UnsetTeamLegalholdWhitelisted :: TeamId -> LegalHoldStore m ()
6364
IsTeamLegalholdWhitelisted :: TeamId -> LegalHoldStore m Bool
64-
-- -- intra actions
65+
-- intra actions
66+
MakeVerifiedRequestFreshManager ::
67+
Fingerprint Rsa ->
68+
HttpsUrl ->
69+
(Http.Request -> Http.Request) ->
70+
LegalHoldStore m (Http.Response LC8.ByteString)
6571
MakeVerifiedRequest ::
6672
Fingerprint Rsa ->
6773
HttpsUrl ->

services/galley/src/Galley/Env.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ data Env = Env
5454
_applog :: Logger,
5555
_manager :: Manager,
5656
_http2Manager :: Http2Manager,
57-
_federator :: Maybe Endpoint, -- FUTUREWORK: should we use a better type here? E.g. to avoid fresh connections all the time?
57+
_federator :: Maybe Endpoint, -- FUTUREWORK: should we use a better type ----- LegalHold.testLHClaimKeys01 FAIL (34.01 s) -----here? E.g. to avoid fresh connections all the time?
5858
_brig :: Endpoint, -- FUTUREWORK: see _federator
5959
_cstate :: ClientState,
6060
_deleteQueue :: Q.Queue DeleteItem,
61-
_extGetManager :: [Fingerprint Rsa] -> IO Manager,
61+
_extGetManager :: (Manager, IORef [Fingerprint Rsa]),
6262
_aEnv :: Maybe Aws.Env,
6363
_mlsKeys :: SignaturePurpose -> MLSKeys,
6464
_rabbitmqChannel :: Maybe (MVar Q.Channel),
@@ -68,7 +68,7 @@ data Env = Env
6868
makeLenses ''Env
6969

7070
-- TODO: somewhat duplicates Brig.App.initExtGetManager
71-
initExtEnv :: [Fingerprint Rsa] -> IO Manager
71+
initExtEnv :: IORef [Fingerprint Rsa] -> IO Manager
7272
initExtEnv fingerprints = do
7373
ctx <- Ssl.context
7474
Ssl.contextAddOption ctx SSL_OP_NO_SSLv2

services/galley/src/Galley/External.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ urlPort (HttpsUrl u) = do
151151

152152
sendMessage :: [Fingerprint Rsa] -> (Request -> Request) -> App ()
153153
sendMessage fprs reqBuilder = do
154-
mkMgr <- view extGetManager
155-
man <- liftIO $ mkMgr fprs
154+
(man, fprVar) <- view extGetManager
155+
modifyIORef' fprVar (nub . (<> fprs))
156156
let req = reqBuilder defaultRequest
157157
liftIO $ withConnection req man $ \_conn ->
158158
Http.withResponse req man (const $ pure ())

services/galley/src/Galley/External/LegalHoldService.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ checkLegalHoldServiceStatus ::
6060
HttpsUrl ->
6161
Sem r ()
6262
checkLegalHoldServiceStatus fpr url = do
63-
resp <- makeVerifiedRequest fpr url reqBuilder
63+
resp <- makeVerifiedRequestFreshManager fpr url reqBuilder
6464
if Bilge.statusCode resp < 400
6565
then pure ()
6666
else do

0 commit comments

Comments
 (0)