From 1855386c1237b7bb78ae86b77522eb032976e852 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Fri, 23 Dec 2022 10:25:32 +0100 Subject: [PATCH 01/14] Move Spar options to the spar package --- libs/wire-api/src/Wire/API/User/Saml.hs | 40 +-------------- services/spar/src/Spar/API.hs | 1 + services/spar/src/Spar/App.hs | 1 + .../spar/src/Spar/CanonicalInterpreter.hs | 1 + services/spar/src/Spar/Data.hs | 1 + services/spar/src/Spar/Options.hs | 51 +++++++++++++++++-- services/spar/src/Spar/Run.hs | 6 +-- services/spar/src/Spar/Scim.hs | 2 +- services/spar/src/Spar/Scim/Auth.hs | 2 +- services/spar/src/Spar/Scim/User.hs | 2 +- .../src/Spar/Sem/AReqIDStore/Cassandra.hs | 1 + .../spar/src/Spar/Sem/AssIDStore/Cassandra.hs | 1 + services/spar/src/Spar/Sem/SAML2/Library.hs | 2 +- .../test-integration/Test/Spar/APISpec.hs | 4 +- .../test-integration/Test/Spar/DataSpec.hs | 1 + .../Test/Spar/Scim/UserSpec.hs | 6 +-- services/spar/test-integration/Util/Core.hs | 3 +- services/spar/test-integration/Util/Types.hs | 2 +- 18 files changed, 69 insertions(+), 58 deletions(-) diff --git a/libs/wire-api/src/Wire/API/User/Saml.hs b/libs/wire-api/src/Wire/API/User/Saml.hs index 4d3939a3f42..eebe6a1f659 100644 --- a/libs/wire-api/src/Wire/API/User/Saml.hs +++ b/libs/wire-api/src/Wire/API/User/Saml.hs @@ -38,13 +38,9 @@ import Data.Time import GHC.TypeLits (KnownSymbol, symbolVal) import GHC.Types (Symbol) import Imports -import SAML2.Util (parseURI', renderURI) -import SAML2.WebSSO (Assertion, AuthnRequest, ID, IdPId) -import qualified SAML2.WebSSO as SAML +import SAML2.WebSSO import SAML2.WebSSO.Types.TH (deriveJSONOptions) -import System.Logger.Extended (LogFormat) import URI.ByteString -import Util.Options import Web.Cookie import Wire.API.User.Orphans () @@ -87,37 +83,6 @@ substituteVar var val = substituteVar' ("$" <> var) val . substituteVar' ("%24" substituteVar' :: ST -> ST -> ST -> ST substituteVar' var val = ST.intercalate val . ST.splitOn var -type Opts = Opts' DerivedOpts - --- FUTUREWORK: Shouldn't these types be in spar, not in wire-api? -data Opts' a = Opts - { saml :: !SAML.Config, - brig :: !Endpoint, - galley :: !Endpoint, - cassandra :: !CassandraOpts, - maxttlAuthreq :: !(TTL "authreq"), - maxttlAuthresp :: !(TTL "authresp"), - -- | The maximum number of SCIM tokens that we will allow teams to have. - maxScimTokens :: !Int, - -- | The maximum size of rich info. Should be in sync with 'Brig.Types.richInfoLimit'. - richInfoLimit :: !Int, - -- | Wire/AWS specific; optional; used to discover Cassandra instance - -- IPs using describe-instances. - discoUrl :: !(Maybe Text), - logNetStrings :: !(Maybe (Last Bool)), - logFormat :: !(Maybe (Last LogFormat)), - -- , optSettings :: !Settings -- (nothing yet; see other services for what belongs in here.) - derivedOpts :: !a - } - deriving (Functor, Show, Generic) - -instance FromJSON (Opts' (Maybe ())) - -data DerivedOpts = DerivedOpts - { derivedOptsScimBaseURI :: !URI - } - deriving (Show, Generic) - -- | (seconds) newtype TTL (tablename :: Symbol) = TTL {fromTTL :: Int32} deriving (Eq, Ord, Show, Num) @@ -134,9 +99,6 @@ data TTLError = TTLTooLong String String | TTLNegative String ttlToNominalDiffTime :: TTL a -> NominalDiffTime ttlToNominalDiffTime (TTL i32) = fromIntegral i32 -maxttlAuthreqDiffTime :: Opts -> NominalDiffTime -maxttlAuthreqDiffTime = ttlToNominalDiffTime . maxttlAuthreq - data SsoSettings = SsoSettings { defaultSsoCode :: !(Maybe IdPId) } diff --git a/services/spar/src/Spar/API.hs b/services/spar/src/Spar/API.hs index 0a81b08c3a7..e0a6cd861b7 100644 --- a/services/spar/src/Spar/API.hs +++ b/services/spar/src/Spar/API.hs @@ -69,6 +69,7 @@ import Spar.App import Spar.CanonicalInterpreter import Spar.Error import qualified Spar.Intra.BrigApp as Brig +import Spar.Options import Spar.Orphans () import Spar.Scim import Spar.Sem.AReqIDStore (AReqIDStore) diff --git a/services/spar/src/Spar/App.hs b/services/spar/src/Spar/App.hs index 429eac99c01..e92f3f41a9e 100644 --- a/services/spar/src/Spar/App.hs +++ b/services/spar/src/Spar/App.hs @@ -64,6 +64,7 @@ import Servant import qualified Servant.Multipart as Multipart import Spar.Error hiding (sparToServerErrorWithLogging) import qualified Spar.Intra.BrigApp as Intra +import Spar.Options import Spar.Orphans () import Spar.Sem.AReqIDStore (AReqIDStore) import Spar.Sem.BrigAccess (BrigAccess) diff --git a/services/spar/src/Spar/CanonicalInterpreter.hs b/services/spar/src/Spar/CanonicalInterpreter.hs index 02475109a2f..75170b8e2df 100644 --- a/services/spar/src/Spar/CanonicalInterpreter.hs +++ b/services/spar/src/Spar/CanonicalInterpreter.hs @@ -33,6 +33,7 @@ import Polysemy.Input (Input, runInputConst) import Servant import Spar.App hiding (sparToServerErrorWithLogging) import Spar.Error +import Spar.Options import Spar.Orphans () import Spar.Sem.AReqIDStore (AReqIDStore) import Spar.Sem.AReqIDStore.Cassandra (aReqIDStoreToCassandra) diff --git a/services/spar/src/Spar/Data.hs b/services/spar/src/Spar/Data.hs index 3c53a9d9aa1..375533c2f62 100644 --- a/services/spar/src/Spar/Data.hs +++ b/services/spar/src/Spar/Data.hs @@ -44,6 +44,7 @@ import Imports import SAML2.Util (renderURI) import qualified SAML2.WebSSO as SAML import qualified SAML2.WebSSO.Types.Email as SAMLEmail +import Spar.Options import Wire.API.User.Saml -- | A lower bound: @schemaVersion <= whatWeFoundOnCassandra@, not @==@. diff --git a/services/spar/src/Spar/Options.hs b/services/spar/src/Spar/Options.hs index de3eed04fb9..3031e137066 100644 --- a/services/spar/src/Spar/Options.hs +++ b/services/spar/src/Spar/Options.hs @@ -19,26 +19,69 @@ -- with this program. If not, see . -- | Reading the Spar config. --- --- The config type itself, 'Opts', is defined in "Spar.Types". module Spar.Options - ( getOpts, + ( Opts' (..), + Opts, + DerivedOpts (..), + getOpts, deriveOpts, readOptsFile, + maxttlAuthreqDiffTime, ) where import Control.Exception import Control.Lens +import Control.Monad.Except +import Data.Aeson hiding (fieldLabelModifier) import qualified Data.ByteString as SBS +import Data.String.Conversions +import Data.Time import qualified Data.Yaml as Yaml import Imports import Options.Applicative +import SAML2.WebSSO import qualified SAML2.WebSSO as SAML +import System.Logger.Extended (LogFormat) import Text.Ascii (ascii) -import URI.ByteString as URI +import URI.ByteString +import Util.Options +import Wire.API.User.Orphans () import Wire.API.User.Saml +type Opts = Opts' DerivedOpts + +data Opts' a = Opts + { saml :: !SAML.Config, + brig :: !Endpoint, + galley :: !Endpoint, + cassandra :: !CassandraOpts, + maxttlAuthreq :: !(TTL "authreq"), + maxttlAuthresp :: !(TTL "authresp"), + -- | The maximum number of SCIM tokens that we will allow teams to have. + maxScimTokens :: !Int, + -- | The maximum size of rich info. Should be in sync with 'Brig.Types.richInfoLimit'. + richInfoLimit :: !Int, + -- | Wire/AWS specific; optional; used to discover Cassandra instance + -- IPs using describe-instances. + discoUrl :: !(Maybe Text), + logNetStrings :: !(Maybe (Last Bool)), + logFormat :: !(Maybe (Last LogFormat)), + -- , optSettings :: !Settings -- (nothing yet; see other services for what belongs in here.) + derivedOpts :: !a + } + deriving (Functor, Show, Generic) + +instance FromJSON (Opts' (Maybe ())) + +data DerivedOpts = DerivedOpts + { derivedOptsScimBaseURI :: !URI + } + deriving (Show, Generic) + +maxttlAuthreqDiffTime :: Opts -> NominalDiffTime +maxttlAuthreqDiffTime = ttlToNominalDiffTime . maxttlAuthreq + type OptsRaw = Opts' (Maybe ()) -- | Throws an exception if no config file is found. diff --git a/services/spar/src/Spar/Run.hs b/services/spar/src/Spar/Run.hs index 80e7013291f..05258779e7e 100644 --- a/services/spar/src/Spar/Run.hs +++ b/services/spar/src/Spar/Run.hs @@ -49,12 +49,12 @@ import Spar.API (API, app) import Spar.App import qualified Spar.Data as Data import Spar.Data.Instances () +import Spar.Options import Spar.Orphans () import System.Logger.Class (Logger) import qualified System.Logger.Extended as Log import Util.Options (casEndpoint, casFilterNodesByDatacentre, casKeyspace, epHost, epPort) import Wire.API.Routes.Version.Wai -import Wire.API.User.Saml as Types import Wire.Sem.Logger.TinyLog ---------------------------------------------------------------------- @@ -62,12 +62,12 @@ import Wire.Sem.Logger.TinyLog initCassandra :: Opts -> Logger -> IO ClientState initCassandra opts lgr = do - let cassOpts = Types.cassandra opts + let cassOpts = cassandra opts connectString <- maybe (Cas.initialContactsPlain (cassOpts ^. casEndpoint . epHost)) (Cas.initialContactsDisco "cassandra_spar" . cs) - (Types.discoUrl opts) + (discoUrl opts) cas <- Cas.init $ Cas.defSettings diff --git a/services/spar/src/Spar/Scim.hs b/services/spar/src/Spar/Scim.hs index 313987866dc..72c3afa041e 100644 --- a/services/spar/src/Spar/Scim.hs +++ b/services/spar/src/Spar/Scim.hs @@ -77,6 +77,7 @@ import Spar.Error ( SparCustomError (SparScimError), SparError, ) +import Spar.Options import Spar.Scim.Auth import Spar.Scim.User import Spar.Sem.BrigAccess (BrigAccess) @@ -96,7 +97,6 @@ import qualified Web.Scim.Schema.Error as Scim import qualified Web.Scim.Schema.Schema as Scim.Schema import qualified Web.Scim.Server as Scim import Wire.API.Routes.Public.Spar -import Wire.API.User.Saml (Opts) import Wire.API.User.Scim import Wire.Sem.Logger (Logger) import Wire.Sem.Now (Now) diff --git a/services/spar/src/Spar/Scim/Auth.hs b/services/spar/src/Spar/Scim/Auth.hs index 0a75c49fb2e..12081181f99 100644 --- a/services/spar/src/Spar/Scim/Auth.hs +++ b/services/spar/src/Spar/Scim/Auth.hs @@ -51,6 +51,7 @@ import Servant (NoContent (NoContent), ServerT, (:<|>) ((:<|>))) import Spar.App (throwSparSem) import qualified Spar.Error as E import qualified Spar.Intra.BrigApp as Intra.Brig +import Spar.Options import Spar.Sem.BrigAccess (BrigAccess) import qualified Spar.Sem.BrigAccess as BrigAccess import Spar.Sem.GalleyAccess (GalleyAccess) @@ -63,7 +64,6 @@ import qualified Web.Scim.Handler as Scim import qualified Web.Scim.Schema.Error as Scim import Wire.API.Routes.Public.Spar (APIScimToken) import Wire.API.User as User -import Wire.API.User.Saml (Opts, maxScimTokens) import Wire.API.User.Scim as Api import Wire.Sem.Now (Now) import qualified Wire.Sem.Now as Now diff --git a/services/spar/src/Spar/Scim/User.hs b/services/spar/src/Spar/Scim/User.hs index c84279743d4..2215547ca49 100644 --- a/services/spar/src/Spar/Scim/User.hs +++ b/services/spar/src/Spar/Scim/User.hs @@ -69,6 +69,7 @@ import qualified SAML2.WebSSO as SAML import Spar.App (getUserByUrefUnsafe, getUserIdByScimExternalId) import qualified Spar.App import qualified Spar.Intra.BrigApp as Brig +import Spar.Options import Spar.Scim.Auth () import Spar.Scim.Types (normalizeLikeStored) import qualified Spar.Scim.Types as ST @@ -102,7 +103,6 @@ import Wire.API.Team.Role import Wire.API.User import Wire.API.User.IdentityProvider (IdP) import qualified Wire.API.User.RichInfo as RI -import Wire.API.User.Saml (Opts, derivedOpts, derivedOptsScimBaseURI, richInfoLimit) import Wire.API.User.Scim (ScimTokenInfo (..)) import qualified Wire.API.User.Scim as ST import Wire.Sem.Logger (Logger) diff --git a/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs b/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs index a5716e0ca3b..8c04ed86927 100644 --- a/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs +++ b/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs @@ -30,6 +30,7 @@ import Polysemy.Input (Input, input) import qualified SAML2.WebSSO as SAML import qualified Spar.Data as Data import Spar.Data.Instances () +import Spar.Options import Spar.Sem.AReqIDStore import Wire.API.User.Saml import Wire.Sem.Now (Now) diff --git a/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs b/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs index ab4a188c553..1465bf8aaf5 100644 --- a/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs +++ b/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs @@ -30,6 +30,7 @@ import Polysemy.Input import qualified SAML2.WebSSO as SAML import qualified Spar.Data as Data import Spar.Data.Instances () +import Spar.Options import Spar.Sem.AssIDStore import Wire.API.User.Saml import Wire.Sem.Now (Now) diff --git a/services/spar/src/Spar/Sem/SAML2/Library.hs b/services/spar/src/Spar/Sem/SAML2/Library.hs index bb434989e39..993b0fa4078 100644 --- a/services/spar/src/Spar/Sem/SAML2/Library.hs +++ b/services/spar/src/Spar/Sem/SAML2/Library.hs @@ -34,6 +34,7 @@ import Polysemy.Internal.Tactics import SAML2.WebSSO hiding (Error) import qualified SAML2.WebSSO as SAML hiding (Error) import Spar.Error (SparCustomError (..), SparError) +import Spar.Options import Spar.Sem.AReqIDStore (AReqIDStore) import qualified Spar.Sem.AReqIDStore as AReqIDStore import Spar.Sem.AssIDStore (AssIDStore) @@ -42,7 +43,6 @@ import Spar.Sem.IdPConfigStore (IdPConfigStore) import qualified Spar.Sem.IdPConfigStore as IdPConfigStore import Spar.Sem.SAML2 import Wire.API.User.IdentityProvider (WireIdP) -import Wire.API.User.Saml import Wire.Sem.Logger (Logger) import qualified Wire.Sem.Logger as Logger diff --git a/services/spar/test-integration/Test/Spar/APISpec.hs b/services/spar/test-integration/Test/Spar/APISpec.hs index c2e5175354e..de1ccc922a4 100644 --- a/services/spar/test-integration/Test/Spar/APISpec.hs +++ b/services/spar/test-integration/Test/Spar/APISpec.hs @@ -75,6 +75,7 @@ import SAML2.WebSSO.Test.Lenses import SAML2.WebSSO.Test.MockResponse import SAML2.WebSSO.Test.Util import qualified Spar.Intra.BrigApp as Intra +import Spar.Options import qualified Spar.Sem.AReqIDStore as AReqIDStore import qualified Spar.Sem.BrigAccess as BrigAccess import qualified Spar.Sem.IdPConfigStore as IdPEffect @@ -94,7 +95,6 @@ import Wire.API.User import Wire.API.User.Client import Wire.API.User.Client.Prekey import Wire.API.User.IdentityProvider -import qualified Wire.API.User.Saml as WireAPI (saml) import Wire.API.User.Scim spec :: SpecWith TestEnv @@ -151,7 +151,7 @@ specMetadata = do mkit mdpath finalizepath = do it ("metadata (" <> mdpath <> ")") $ do env <- ask - let sparHost = env ^. teOpts . to WireAPI.saml . SAML.cfgSPSsoURI . to (cs . SAML.renderURI) + let sparHost = env ^. teOpts . to saml . SAML.cfgSPSsoURI . to (cs . SAML.renderURI) fragments = [ "md:SPSSODescriptor", "validUntil", diff --git a/services/spar/test-integration/Test/Spar/DataSpec.hs b/services/spar/test-integration/Test/Spar/DataSpec.hs index 494035c42f4..46f7fe88e64 100644 --- a/services/spar/test-integration/Test/Spar/DataSpec.hs +++ b/services/spar/test-integration/Test/Spar/DataSpec.hs @@ -33,6 +33,7 @@ import SAML2.WebSSO as SAML import Spar.App as App import Spar.Error (IdpDbError (IdpNotFound), SparCustomError (IdpDbError)) import Spar.Intra.BrigApp (veidFromUserSSOId) +import Spar.Options import qualified Spar.Sem.AReqIDStore as AReqIDStore import qualified Spar.Sem.AssIDStore as AssIDStore import qualified Spar.Sem.IdPConfigStore as IdPEffect diff --git a/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs b/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs index 3429af354b6..342fbbb5cc2 100644 --- a/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs +++ b/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs @@ -62,6 +62,7 @@ import qualified SAML2.WebSSO.Test.MockResponse as SAML import SAML2.WebSSO.Test.Util.TestSP (makeSampleIdPMetadata) import qualified SAML2.WebSSO.Test.Util.Types as SAML import qualified Spar.Intra.BrigApp as Intra +import Spar.Options import Spar.Scim import Spar.Scim.Types (normalizeLikeStored) import qualified Spar.Scim.User as SU @@ -89,7 +90,6 @@ import Wire.API.User hiding (scimExternalId) import Wire.API.User.IdentityProvider (IdP) import qualified Wire.API.User.IdentityProvider as User import Wire.API.User.RichInfo -import qualified Wire.API.User.Saml as Spar.Types import qualified Wire.API.User.Scim as Spar.Types import qualified Wire.API.User.Search as Search @@ -1585,7 +1585,7 @@ testScimSideIsUpdated = do liftIO $ updatedUser `shouldBe` storedUser' -- Check that the updated user also matches the data that we sent with -- 'updateUser' - richInfoLimit <- view (teOpts . to Spar.Types.richInfoLimit) + richInfoLimit <- view (teOpts . to richInfoLimit) liftIO $ do Right (Scim.value (Scim.thing storedUser')) `shouldBe` (whatSparReturnsFor idp richInfoLimit (setPreferredLanguage defLang user') <&> setDefaultRoleIfEmpty) Scim.id (Scim.thing storedUser') `shouldBe` Scim.id (Scim.thing storedUser) @@ -1641,7 +1641,7 @@ testUpdateSameHandle = do storedUser' <- getUser tok userid liftIO $ updatedUser `shouldBe` storedUser' -- Check that the updated user also matches the data that we sent with 'updateUser' - richInfoLimit <- view (teOpts . to Spar.Types.richInfoLimit) + richInfoLimit <- view (teOpts . to richInfoLimit) liftIO $ do Right (Scim.value (Scim.thing storedUser')) `shouldBe` (whatSparReturnsFor idp richInfoLimit (setPreferredLanguage defLang user') <&> setDefaultRoleIfEmpty) Scim.id (Scim.thing storedUser') `shouldBe` Scim.id (Scim.thing storedUser) diff --git a/services/spar/test-integration/Util/Core.hs b/services/spar/test-integration/Util/Core.hs index 50505ae9979..b28898d87a2 100644 --- a/services/spar/test-integration/Util/Core.hs +++ b/services/spar/test-integration/Util/Core.hs @@ -183,7 +183,7 @@ import qualified Spar.App as Spar import Spar.CanonicalInterpreter import Spar.Error (SparError) import qualified Spar.Intra.BrigApp as Intra -import qualified Spar.Options +import Spar.Options import Spar.Run import qualified Spar.Sem.IdPConfigStore as IdPConfigStore import qualified Spar.Sem.SAMLUserStore as SAMLUserStore @@ -215,7 +215,6 @@ import qualified Wire.API.User as User import Wire.API.User.Activation import Wire.API.User.Auth hiding (Cookie) import Wire.API.User.IdentityProvider -import Wire.API.User.Saml import Wire.API.User.Scim (runValidExternalIdEither) import Wire.Sem.Logger.TinyLog diff --git a/services/spar/test-integration/Util/Types.hs b/services/spar/test-integration/Util/Types.hs index 04bbfa29781..ba3abc8615c 100644 --- a/services/spar/test-integration/Util/Types.hs +++ b/services/spar/test-integration/Util/Types.hs @@ -54,10 +54,10 @@ import Imports import SAML2.WebSSO.Types.TH (deriveJSONOptions) import Spar.API () import qualified Spar.App as Spar +import Spar.Options import Test.Hspec (pendingWith) import Util.Options import Wire.API.User.IdentityProvider (WireIdPAPIVersion) -import Wire.API.User.Saml type BrigReq = Request -> Request From e560cc4069a23666cce3e4c1d9d92e94abb3e8af Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Wed, 21 Dec 2022 16:28:18 +0100 Subject: [PATCH 02/14] Add a disabledAPIVersions option --- libs/wire-api/src/Wire/API/Routes/Version/Wai.hs | 8 ++++---- services/brig/src/Brig/Options.hs | 5 ++++- services/brig/src/Brig/Run.hs | 3 ++- services/cannon/src/Cannon/Options.hs | 5 ++++- services/cannon/src/Cannon/Run.hs | 2 +- services/cargohold/src/CargoHold/Options.hs | 4 +++- services/cargohold/src/CargoHold/Run.hs | 2 +- services/galley/src/Galley/Options.hs | 5 ++++- services/galley/src/Galley/Run.hs | 2 +- services/gundeck/src/Gundeck/Options.hs | 4 +++- services/gundeck/src/Gundeck/Run.hs | 2 +- services/proxy/src/Proxy/Options.hs | 8 ++++++-- services/proxy/src/Proxy/Run.hs | 2 +- services/spar/src/Spar/Options.hs | 3 ++- services/spar/src/Spar/Run.hs | 2 +- 15 files changed, 38 insertions(+), 19 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Version/Wai.hs b/libs/wire-api/src/Wire/API/Routes/Version/Wai.hs index 25a4add2bc0..545acdeae4d 100644 --- a/libs/wire-api/src/Wire/API/Routes/Version/Wai.hs +++ b/libs/wire-api/src/Wire/API/Routes/Version/Wai.hs @@ -28,12 +28,12 @@ import Network.Wai.Utilities.Response import Wire.API.Routes.Version -- | Strip off version prefix. Return 404 if the version is not supported. -versionMiddleware :: Middleware -versionMiddleware app req k = case parseVersion (removeVersionHeader req) of +versionMiddleware :: Set Version -> Middleware +versionMiddleware disabledAPIVersions app req k = case parseVersion (removeVersionHeader req) of Nothing -> app req k Just (req', n) -> case mkVersion n of - Just v -> app (addVersionHeader v req') k - Nothing -> + Just v | v `notElem` disabledAPIVersions -> app (addVersionHeader v req') k + _ -> k $ errorRs' $ mkError HTTP.status404 "unsupported-version" $ diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index 464dc3d62f2..5f59c045697 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -52,6 +52,7 @@ import Imports import qualified Network.DNS as DNS import System.Logger.Extended (Level, LogFormat) import Util.Options +import Wire.API.Routes.Version import qualified Wire.API.Team.Feature as Public import Wire.API.User import Wire.API.User.Search (FederatedUserSearchPolicy) @@ -587,8 +588,10 @@ data Settings = Settings setSftListAllServers :: Maybe ListAllSFTServers, setEnableMLS :: Maybe Bool, setKeyPackageMaximumLifetime :: Maybe NominalDiffTime, - -- | When set, development API versions are advertised to clients. + -- | When set, development API versions are advertised to clients as supported. setEnableDevelopmentVersions :: Maybe Bool, + -- | Disabled versions are not advertised and are completely disabled. + setDisabledAPIVersions :: Maybe (Set Version), -- | Minimum delay in seconds between consecutive attempts to generate a new verification code. -- use `set2FACodeGenerationDelaySecs` as the getter function which always provides a default value set2FACodeGenerationDelaySecsInternal :: !(Maybe Int), diff --git a/services/brig/src/Brig/Run.hs b/services/brig/src/Brig/Run.hs index 62c74660980..8eb7d753f97 100644 --- a/services/brig/src/Brig/Run.hs +++ b/services/brig/src/Brig/Run.hs @@ -130,7 +130,8 @@ mkApp o = do middleware :: Env -> (RequestId -> Wai.Application) -> Wai.Application middleware e = - versionMiddleware -- this rewrites the request, so it must be at the top (i.e. applied last) + -- this rewrites the request, so it must be at the top (i.e. applied last) + versionMiddleware (fold (setDisabledAPIVersions (optSettings o))) . Metrics.servantPlusWAIPrometheusMiddleware (sitemap @BrigCanonicalEffects) (Proxy @ServantCombinedAPI) . GZip.gunzip . GZip.gzip GZip.def diff --git a/services/cannon/src/Cannon/Options.hs b/services/cannon/src/Cannon/Options.hs index e2117ee8c36..bce5cba50cc 100644 --- a/services/cannon/src/Cannon/Options.hs +++ b/services/cannon/src/Cannon/Options.hs @@ -34,6 +34,7 @@ module Cannon.Options gracePeriodSeconds, millisecondsBetweenBatches, minBatchSize, + disabledAPIVersions, DrainOpts, ) where @@ -42,6 +43,7 @@ import Control.Lens (makeFields) import Data.Aeson.APIFieldJsonTH import Imports import System.Logger.Extended (Level, LogFormat) +import Wire.API.Routes.Version data Cannon = Cannon { _cannonHost :: !String, @@ -88,7 +90,8 @@ data Opts = Opts _optsLogLevel :: !Level, _optsLogNetStrings :: !(Maybe (Last Bool)), _optsLogFormat :: !(Maybe (Last LogFormat)), - _optsDrainOpts :: DrainOpts + _optsDrainOpts :: DrainOpts, + _optsDisabledAPIVersions :: Maybe (Set Version) } deriving (Eq, Show, Generic) diff --git a/services/cannon/src/Cannon/Run.hs b/services/cannon/src/Cannon/Run.hs index c5a30103aba..8fb26e7e4f2 100644 --- a/services/cannon/src/Cannon/Run.hs +++ b/services/cannon/src/Cannon/Run.hs @@ -77,7 +77,7 @@ run o = do s <- newSettings $ Server (o ^. cannon . host) (o ^. cannon . port) (applog e) m (Just idleTimeout) let middleware :: Wai.Middleware middleware = - versionMiddleware + versionMiddleware (fold (o ^. disabledAPIVersions)) . servantPrometheusMiddleware (Proxy @CombinedAPI) . Gzip.gzip Gzip.def . catchErrors g [Right m] diff --git a/services/cargohold/src/CargoHold/Options.hs b/services/cargohold/src/CargoHold/Options.hs index 7a96fdef700..c6c7076e991 100644 --- a/services/cargohold/src/CargoHold/Options.hs +++ b/services/cargohold/src/CargoHold/Options.hs @@ -30,6 +30,7 @@ import Imports import System.Logger.Extended (Level, LogFormat) import Util.Options import Util.Options.Common +import Wire.API.Routes.Version -- | AWS CloudFront settings. data CloudFrontOpts = CloudFrontOpts @@ -132,7 +133,8 @@ data Settings = Settings -- Remember to keep it the same in Galley and in Brig. -- This is referred to as the 'backend domain' in the public documentation; See -- https://docs.wire.com/how-to/install/configure-federation.html#choose-a-backend-domain-name - _setFederationDomain :: !Domain + _setFederationDomain :: !Domain, + _setDisabledAPIVersions :: !(Maybe (Set Version)) } deriving (Show, Generic) diff --git a/services/cargohold/src/CargoHold/Run.hs b/services/cargohold/src/CargoHold/Run.hs index d0675dcf5af..b654a165926 100644 --- a/services/cargohold/src/CargoHold/Run.hs +++ b/services/cargohold/src/CargoHold/Run.hs @@ -82,7 +82,7 @@ mkApp o = Codensity $ \k -> where middleware :: Env -> Wai.Middleware middleware e = - versionMiddleware + versionMiddleware (fold (o ^. optSettings . setDisabledAPIVersions)) . servantPrometheusMiddleware (Proxy @CombinedAPI) . GZip.gzip GZip.def . catchErrors (e ^. appLogger) [Right $ e ^. metrics] diff --git a/services/galley/src/Galley/Options.hs b/services/galley/src/Galley/Options.hs index edb3850d29b..844ca390648 100644 --- a/services/galley/src/Galley/Options.hs +++ b/services/galley/src/Galley/Options.hs @@ -25,6 +25,7 @@ module Galley.Options setExposeInvitationURLsTeamAllowlist, setMaxConvSize, setIntraListing, + setDisabledAPIVersions, setConversationCodeURI, setConcurrentDeletionEvents, setDeleteConvThrottleMillis, @@ -66,6 +67,7 @@ import Imports import System.Logger.Extended (Level, LogFormat) import Util.Options import Util.Options.Common +import Wire.API.Routes.Version import Wire.API.Team.Member data Settings = Settings @@ -113,7 +115,8 @@ data Settings = Settings _setEnableIndexedBillingTeamMembers :: !(Maybe Bool), _setMlsPrivateKeyPaths :: !(Maybe MLSPrivateKeyPaths), -- | FUTUREWORK: 'setFeatureFlags' should be renamed to 'setFeatureConfigs' in all types. - _setFeatureFlags :: !FeatureFlags + _setFeatureFlags :: !FeatureFlags, + _setDisabledAPIVersions :: Maybe (Set Version) } deriving (Show, Generic) diff --git a/services/galley/src/Galley/Run.hs b/services/galley/src/Galley/Run.hs index 81dfa216da9..b528a6c0547 100644 --- a/services/galley/src/Galley/Run.hs +++ b/services/galley/src/Galley/Run.hs @@ -93,7 +93,7 @@ mkApp opts = let logger = env ^. App.applog let middlewares = - versionMiddleware + versionMiddleware (opts ^. optSettings . setDisabledAPIVersions . traverse) . servantPlusWAIPrometheusMiddleware API.sitemap (Proxy @CombinedAPI) . GZip.gunzip . GZip.gzip GZip.def diff --git a/services/gundeck/src/Gundeck/Options.hs b/services/gundeck/src/Gundeck/Options.hs index 3fa6d2044a0..95eb235f41d 100644 --- a/services/gundeck/src/Gundeck/Options.hs +++ b/services/gundeck/src/Gundeck/Options.hs @@ -28,6 +28,7 @@ import Imports import System.Logger.Extended (Level, LogFormat) import Util.Options import Util.Options.Common +import Wire.API.Routes.Version newtype NotificationTTL = NotificationTTL {notificationTTLSeconds :: Word32} @@ -73,7 +74,8 @@ data Settings = Settings -- ensures that there is only one request every 20 seconds. -- However, that parameter is not honoured when using fake-sqs -- (where throttling can thus make sense) - _setSqsThrottleMillis :: !(Maybe Int) + _setSqsThrottleMillis :: !(Maybe Int), + _setDisabledAPIVersions :: !(Maybe (Set Version)) } deriving (Show, Generic) diff --git a/services/gundeck/src/Gundeck/Run.hs b/services/gundeck/src/Gundeck/Run.hs index 012c7802d07..c8fc2eb9088 100644 --- a/services/gundeck/src/Gundeck/Run.hs +++ b/services/gundeck/src/Gundeck/Run.hs @@ -80,7 +80,7 @@ run o = do where middleware :: Env -> Wai.Middleware middleware e = - versionMiddleware + versionMiddleware (fold (o ^. optSettings . setDisabledAPIVersions)) . waiPrometheusMiddleware sitemap . GZip.gunzip . GZip.gzip GZip.def diff --git a/services/proxy/src/Proxy/Options.hs b/services/proxy/src/Proxy/Options.hs index 2397fd04389..58259956ba6 100644 --- a/services/proxy/src/Proxy/Options.hs +++ b/services/proxy/src/Proxy/Options.hs @@ -28,6 +28,7 @@ module Proxy.Options logNetStrings, logFormat, mockOpts, + disabledAPIVersions, ) where @@ -36,6 +37,7 @@ import Data.Aeson import Data.Aeson.TH import Imports import System.Logger.Extended (Level (Debug), LogFormat) +import Wire.API.Routes.Version data Opts = Opts { -- | Host to listen on @@ -54,7 +56,8 @@ data Opts = Opts -- | Use netstrings encoding _logNetStrings :: !(Maybe (Last Bool)), -- | choose Encoding - _logFormat :: !(Maybe (Last LogFormat)) + _logFormat :: !(Maybe (Last LogFormat)), + _disabledAPIVersions :: !(Maybe (Set Version)) } deriving (Show, Generic) @@ -73,5 +76,6 @@ mockOpts secrets = _maxConns = 0, _logLevel = Debug, _logNetStrings = pure $ pure $ True, - _logFormat = mempty + _logFormat = mempty, + _disabledAPIVersions = mempty } diff --git a/services/proxy/src/Proxy/Run.hs b/services/proxy/src/Proxy/Run.hs index 69b209b0bb2..1eb6f1c1e9f 100644 --- a/services/proxy/src/Proxy/Run.hs +++ b/services/proxy/src/Proxy/Run.hs @@ -40,7 +40,7 @@ run o = do let rtree = compile (sitemap e) let app r k = runProxy e r (route rtree r k) let middleware = - versionMiddleware + versionMiddleware (fold (o ^. disabledAPIVersions)) . waiPrometheusMiddleware (sitemap e) . catchErrors (e ^. applog) [Right m] runSettingsWithShutdown s (middleware app) Nothing `finally` destroyEnv e diff --git a/services/spar/src/Spar/Options.hs b/services/spar/src/Spar/Options.hs index 3031e137066..ca2da7a3b9c 100644 --- a/services/spar/src/Spar/Options.hs +++ b/services/spar/src/Spar/Options.hs @@ -46,6 +46,7 @@ import System.Logger.Extended (LogFormat) import Text.Ascii (ascii) import URI.ByteString import Util.Options +import Wire.API.Routes.Version import Wire.API.User.Orphans () import Wire.API.User.Saml @@ -67,7 +68,7 @@ data Opts' a = Opts discoUrl :: !(Maybe Text), logNetStrings :: !(Maybe (Last Bool)), logFormat :: !(Maybe (Last LogFormat)), - -- , optSettings :: !Settings -- (nothing yet; see other services for what belongs in here.) + disabledAPIVersions :: !(Maybe (Set Version)), derivedOpts :: !a } deriving (Functor, Show, Generic) diff --git a/services/spar/src/Spar/Run.hs b/services/spar/src/Spar/Run.hs index 05258779e7e..89b2ff6aec0 100644 --- a/services/spar/src/Spar/Run.hs +++ b/services/spar/src/Spar/Run.hs @@ -115,7 +115,7 @@ mkApp sparCtxOpts = do . Bilge.port (sparCtxOpts ^. to galley . epPort) $ Bilge.empty let wrappedApp = - versionMiddleware + versionMiddleware (fold (disabledAPIVersions sparCtxOpts)) . WU.heavyDebugLogging heavyLogOnly logLevel sparCtxLogger . servantPrometheusMiddleware (Proxy @API) . WU.catchErrors sparCtxLogger [] From 3252d48fba1a6ba5a3225c4e194d823846162480 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Fri, 23 Dec 2022 10:48:43 +0100 Subject: [PATCH 03/14] Do not advertise disabledAPIVersionsListed versions --- services/brig/src/Brig/Options.hs | 3 ++- services/brig/src/Brig/Version.hs | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index 5f59c045697..941a683aba1 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -862,7 +862,8 @@ Lens.makeLensesFor ("setFederationDomainConfigs", "federationDomainConfigs"), ("setEnableDevelopmentVersions", "enableDevelopmentVersions"), ("setRestrictUserCreation", "restrictUserCreation"), - ("setEnableMLS", "enableMLS") + ("setEnableMLS", "enableMLS"), + ("setDisabledAPIVersions", "disabledAPIVersions") ] ''Settings diff --git a/services/brig/src/Brig/Version.hs b/services/brig/src/Brig/Version.hs index 73f7f1fd749..54c63ebfe1a 100644 --- a/services/brig/src/Brig/Version.hs +++ b/services/brig/src/Brig/Version.hs @@ -21,6 +21,7 @@ import Brig.API.Handler import Brig.App import Brig.Options import Control.Lens +import qualified Data.Set as Set import Imports import Servant (ServerT) import Wire.API.Routes.Named @@ -31,12 +32,14 @@ versionAPI = Named $ do fed <- view federator dom <- viewFederationDomain dev <- view (settings . enableDevelopmentVersions . to (fromMaybe False)) + disabledVersions <- view (settings . disabledAPIVersions . traverse) + let allVersions = Set.difference (Set.fromList supportedVersions) disabledVersions let supported - | dev = supportedVersions - | otherwise = supportedVersions \\ developmentVersions + | dev = allVersions + | otherwise = Set.difference allVersions (Set.fromList developmentVersions) pure $ VersionInfo - { vinfoSupported = supported, + { vinfoSupported = toList supported, vinfoDevelopment = developmentVersions, vinfoFederation = isJust fed, vinfoDomain = dom From 4b6bf48e6e8bd610e9654572e9eeb730d8576bd9 Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Wed, 4 Jan 2023 10:26:41 +0100 Subject: [PATCH 04/14] Don't advertise disabled development version --- services/brig/src/Brig/Version.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/brig/src/Brig/Version.hs b/services/brig/src/Brig/Version.hs index 54c63ebfe1a..acf7603d76b 100644 --- a/services/brig/src/Brig/Version.hs +++ b/services/brig/src/Brig/Version.hs @@ -34,13 +34,14 @@ versionAPI = Named $ do dev <- view (settings . enableDevelopmentVersions . to (fromMaybe False)) disabledVersions <- view (settings . disabledAPIVersions . traverse) let allVersions = Set.difference (Set.fromList supportedVersions) disabledVersions - let supported + devVersions = Set.difference (Set.fromList developmentVersions) disabledVersions + supported | dev = allVersions - | otherwise = Set.difference allVersions (Set.fromList developmentVersions) + | otherwise = Set.difference allVersions devVersions pure $ VersionInfo { vinfoSupported = toList supported, - vinfoDevelopment = developmentVersions, + vinfoDevelopment = toList devVersions, vinfoFederation = isJust fed, vinfoDomain = dom } From d482ed050bcb38313628871f102279b185b8614b Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Tue, 3 Jan 2023 17:36:52 +0100 Subject: [PATCH 05/14] Add integration tests --- services/brig/test/integration/API/Version.hs | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/services/brig/test/integration/API/Version.hs b/services/brig/test/integration/API/Version.hs index 4995d8754ef..b9e209a39e7 100644 --- a/services/brig/test/integration/API/Version.hs +++ b/services/brig/test/integration/API/Version.hs @@ -20,13 +20,17 @@ module API.Version (tests) where import Bilge import Bilge.Assert import Brig.Options +import qualified Brig.Options as Opt import Control.Lens ((?~)) +import Control.Monad.Catch (MonadCatch) +import qualified Data.Set as Set import Imports import qualified Network.Wai.Utilities.Error as Wai import Test.Tasty import Test.Tasty.HUnit import Util import Wire.API.Routes.Version +import Wire.API.User tests :: Manager -> Opts -> Brig -> TestTree tests p opts brig = @@ -36,7 +40,10 @@ tests p opts brig = test p "GET /v1/api-version" $ testVersionV1 brig, test p "GET /api-version (with dev)" $ testDevVersion opts brig, test p "GET /v500/api-version" $ testUnsupportedVersion brig, - test p "GET /api-version (federation info)" $ testFederationDomain opts brig + test p "GET /api-version (federation info)" $ testFederationDomain opts brig, + test p "Disabled version makes it unsupported" $ testDisabledVersionIsUnsupported opts brig, + test p "Disabled version is not advertised" $ testVersionDisabledSupportedVersion opts brig, + test p "Disabled dev version is not advertised" $ testVersionDisabledDevelopmentVersion opts brig ] testVersion :: Brig -> Http () @@ -86,3 +93,68 @@ testFederationDomain opts brig = do liftIO $ do vinfoFederation vinfo @?= True vinfoDomain vinfo @?= domain + +testDisabledVersionIsUnsupported :: Opts -> Brig -> Http () +testDisabledVersionIsUnsupported opts brig = do + uid <- userId <$> randomUser brig + + get (apiVersion "v2" . brig . path "/self" . zUser uid) + !!! const 200 === statusCode + + withSettingsOverrides + ( opts + & Opt.optionSettings + . Opt.disabledAPIVersions + ?~ Set.fromList [V2] + ) + $ do + err <- + responseJsonError + =<< get (apiVersion "v2" . brig . path "/self" . zUser uid) + Brig -> Http () +testVersionDisabledSupportedVersion opts brig = do + vinfo <- getVersionInfo brig + liftIO $ filter (== V2) (vinfoSupported vinfo) @?= [V2] + disabledVersionIsNotAdvertised opts brig V2 + +testVersionDisabledDevelopmentVersion :: Opts -> Brig -> Http () +testVersionDisabledDevelopmentVersion opts brig = do + vinfo <- getVersionInfo brig + for_ (listToMaybe (vinfoDevelopment vinfo)) $ \devVersion -> do + liftIO $ filter (== devVersion) (vinfoDevelopment vinfo) @?= [devVersion] + disabledVersionIsNotAdvertised opts brig devVersion + +disabledVersionIsNotAdvertised :: Opts -> Brig -> Version -> Http () +disabledVersionIsNotAdvertised opts brig version = + withSettingsOverrides + ( opts + & Opt.optionSettings + . Opt.disabledAPIVersions + ?~ Set.fromList [version] + ) + $ do + vinfo <- getVersionInfo brig + liftIO $ filter (== version) (vinfoSupported vinfo) @?= [] + liftIO $ filter (== version) (vinfoDevelopment vinfo) @?= [] + +getVersionInfo :: + (MonadIO m, MonadCatch m, MonadFail m, MonadHttp m, HasCallStack) => + Brig -> + m VersionInfo +getVersionInfo brig = + responseJsonError + =<< get (unversioned . brig . path "/api-version") + Date: Wed, 4 Jan 2023 11:40:19 +0100 Subject: [PATCH 06/14] Fix bug in cargho helm chart If .Values.config.settings is not set then the template will render to empty string causing runtime problems. Federation domain is a required paramter. The change in this commit turns the runtime error into a error at template evaluation. --- charts/cargohold/templates/configmap.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/charts/cargohold/templates/configmap.yaml b/charts/cargohold/templates/configmap.yaml index 942185bda33..05f0cf89f0d 100644 --- a/charts/cargohold/templates/configmap.yaml +++ b/charts/cargohold/templates/configmap.yaml @@ -40,8 +40,6 @@ data: {{- end }} settings: - {{- with .Values.config.settings }} maxTotalBytes: 5368709120 downloadLinkTTL: 300 # Seconds - federationDomain: {{ .federationDomain }} - {{- end }} + federationDomain: {{ .Values.config.settings.federationDomain }} From e4cc30b65daa5b2dfa07fd1ba99e9274cd1fe668 Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Wed, 4 Jan 2023 14:42:35 +0100 Subject: [PATCH 07/14] Fix bug in helmfile-single Federation domain is a required parameter for carghold --- hack/helmfile-single.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hack/helmfile-single.yaml b/hack/helmfile-single.yaml index 3d75ce0d8bc..790412bf71f 100644 --- a/hack/helmfile-single.yaml +++ b/hack/helmfile-single.yaml @@ -73,3 +73,5 @@ releases: value: {{ .Values.federationDomain }} - name: galley.config.settings.federationDomain value: {{ .Values.federationDomain }} + - name: cargohold.config.settings.federationDomain + value: {{ .Values.federationDomain }} From 6c902fbb0a755b8ef74cb1d433e12c36afd75c39 Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Wed, 4 Jan 2023 17:40:22 +0100 Subject: [PATCH 08/14] Add config params to all helm charts --- charts/brig/templates/configmap.yaml | 3 +++ charts/brig/values.yaml | 3 +++ charts/cannon/templates/configmap.yaml | 4 ++++ charts/cannon/values.yaml | 4 ++++ charts/cargohold/templates/configmap.yaml | 15 ++++++++++++--- charts/cargohold/values.yaml | 7 +++++++ charts/galley/templates/configmap.yaml | 3 +++ charts/galley/values.yaml | 3 +++ charts/gundeck/templates/configmap.yaml | 4 ++++ charts/gundeck/values.yaml | 4 ++++ charts/proxy/templates/configmap.yaml | 4 +++- charts/proxy/values.yaml | 3 +++ charts/spar/templates/configmap.yaml | 6 +++++- charts/spar/values.yaml | 3 +++ 14 files changed, 61 insertions(+), 5 deletions(-) diff --git a/charts/brig/templates/configmap.yaml b/charts/brig/templates/configmap.yaml index df36b2331bf..a62139035ab 100644 --- a/charts/brig/templates/configmap.yaml +++ b/charts/brig/templates/configmap.yaml @@ -299,5 +299,8 @@ data: {{- if .setEnableMLS }} setEnableMLS: {{ .setEnableMLS }} {{- end }} + {{- if .setDisabledAPIVersions }} + setDisabledAPIVersions: {{ .setDisabledAPIVersions }} + {{- end }} {{- end }} {{- end }} diff --git a/charts/brig/values.yaml b/charts/brig/values.yaml index 99418a4c6fa..6f97219f49c 100644 --- a/charts/brig/values.yaml +++ b/charts/brig/values.yaml @@ -87,6 +87,9 @@ config: setNonceTtlSecs: 300 # 5 minutes setDpopMaxSkewSecs: 1 setDpopTokenExpirationTimeSecs: 300 # 5 minutes + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # setDisabledAPIVersions: [ 3 ] smtp: passwordFile: /etc/wire/brig/secrets/smtp-password.txt proxy: {} diff --git a/charts/cannon/templates/configmap.yaml b/charts/cannon/templates/configmap.yaml index 256dae79e49..940d6013065 100644 --- a/charts/cannon/templates/configmap.yaml +++ b/charts/cannon/templates/configmap.yaml @@ -19,6 +19,10 @@ data: millisecondsBetweenBatches: {{ .Values.config.drainOpts.millisecondsBetweenBatches }} minBatchSize: {{ .Values.config.drainOpts.minBatchSize }} + {{- if .Values.config.disabledAPIVersions }} + disabledAPIVersions: {{ .Values.config.disabledAPIVersions }} + {{- end }} + kind: ConfigMap metadata: name: cannon diff --git a/charts/cannon/values.yaml b/charts/cannon/values.yaml index 41f0c89106e..91426031608 100644 --- a/charts/cannon/values.yaml +++ b/charts/cannon/values.yaml @@ -22,6 +22,10 @@ config: millisecondsBetweenBatches: 50 minBatchSize: 20 + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # disabledAPIVersions: [ 3 ] + metrics: serviceMonitor: enabled: false diff --git a/charts/cargohold/templates/configmap.yaml b/charts/cargohold/templates/configmap.yaml index 05f0cf89f0d..5f6cd7cbc4c 100644 --- a/charts/cargohold/templates/configmap.yaml +++ b/charts/cargohold/templates/configmap.yaml @@ -40,6 +40,15 @@ data: {{- end }} settings: - maxTotalBytes: 5368709120 - downloadLinkTTL: 300 # Seconds - federationDomain: {{ .Values.config.settings.federationDomain }} + {{- with .Values.config.settings }} + {{- if .maxTotalBytes }} + maxTotalBytes: {{ .maxTotalBytes }} + {{- end }} + {{- if .downloadLinkTTL }} + downloadLinkTTL: {{ .downloadLinkTTL }} + {{- end }} + federationDomain: {{ .federationDomain }} + {{- if .disabledAPIVersions }} + disabledAPIVersions: {{ .disabledAPIVersions }} + {{- end }} + {{- end }} diff --git a/charts/cargohold/values.yaml b/charts/cargohold/values.yaml index 76a59b0811f..83411e0035e 100644 --- a/charts/cargohold/values.yaml +++ b/charts/cargohold/values.yaml @@ -23,6 +23,13 @@ config: region: "eu-west-1" s3Bucket: assets proxy: {} + settings: + maxTotalBytes: 5368709120 + downloadLinkTTL: 300 # Seconds + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # disabledAPIVersions: [ 2 ] + serviceAccount: # When setting this to 'false', either make sure that a service account named # 'cargohold' exists or change the 'name' field to 'default' diff --git a/charts/galley/templates/configmap.yaml b/charts/galley/templates/configmap.yaml index e5a4f7864a6..a761fb24fd5 100644 --- a/charts/galley/templates/configmap.yaml +++ b/charts/galley/templates/configmap.yaml @@ -69,6 +69,9 @@ data: ed25519: "/etc/wire/galley/secrets/removal_ed25519.pem" {{- end }} {{- end -}} + {{- if .settings.disabledAPIVersions }} + disabledAPIVersions: {{ .settings.disabledAPIVersions }} + {{- end }} {{- if .settings.featureFlags }} featureFlags: sso: {{ .settings.featureFlags.sso }} diff --git a/charts/galley/values.yaml b/charts/galley/values.yaml index 7e20021638a..8f260a0abe8 100644 --- a/charts/galley/values.yaml +++ b/charts/galley/values.yaml @@ -32,6 +32,9 @@ config: # Before making indexedBillingTeamMember true while upgrading, please # refer to notes here: https://github.com/wireapp/wire-server-deploy/releases/tag/v2020-05-15 indexedBillingTeamMember: false + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # disabledAPIVersions: [ 3 ] featureFlags: # see #RefConfigOptions in `/docs/reference` (https://github.com/wireapp/wire-server/) appLock: defaults: diff --git a/charts/gundeck/templates/configmap.yaml b/charts/gundeck/templates/configmap.yaml index d2b9a18ccc4..2349e68cc42 100644 --- a/charts/gundeck/templates/configmap.yaml +++ b/charts/gundeck/templates/configmap.yaml @@ -53,6 +53,10 @@ data: {{- if hasKey . "perNativePushConcurrency" }} perNativePushConcurrency: {{ .perNativePushConcurrency }} {{- end }} + {{- if .disabledAPIVersions }} + disabledAPIVersions: {{ .disabledAPIVersions }} + {{- end }} + # disabledAPIVersions: [ 2 ] maxConcurrentNativePushes: soft: {{ .maxConcurrentNativePushes.soft }} {{- if hasKey .maxConcurrentNativePushes "hard" }} diff --git a/charts/gundeck/values.yaml b/charts/gundeck/values.yaml index 83ed95df1a5..3f8a5472297 100644 --- a/charts/gundeck/values.yaml +++ b/charts/gundeck/values.yaml @@ -35,6 +35,10 @@ config: # perNativePushConcurrency: 32 maxConcurrentNativePushes: soft: 1000 + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # disabledAPIVersions: [ 3 ] + serviceAccount: # When setting this to 'false', either make sure that a service account named # 'gundeck' exists or change the 'name' field to 'default' diff --git a/charts/proxy/templates/configmap.yaml b/charts/proxy/templates/configmap.yaml index 5af2ebe10c9..54648797524 100644 --- a/charts/proxy/templates/configmap.yaml +++ b/charts/proxy/templates/configmap.yaml @@ -7,7 +7,9 @@ data: logFormat: {{ .Values.config.logFormat }} logLevel: {{ .Values.config.logLevel }} logNetStrings: {{ .Values.config.logNetStrings }} - + {{- if .Values.config.disabledAPIVersions }} + disabledAPIVersions: {{ .Values.config.disabledAPIVersions }} + {{- end }} host: 0.0.0.0 port: {{ .Values.service.internalPort }} httpPoolSize: 1000 diff --git a/charts/proxy/values.yaml b/charts/proxy/values.yaml index 2e527e91db8..6dd53032a90 100644 --- a/charts/proxy/values.yaml +++ b/charts/proxy/values.yaml @@ -19,3 +19,6 @@ config: logFormat: StructuredJSON logNetStrings: false proxy: {} + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # disabledAPIVersions: [ 3 ] diff --git a/charts/spar/templates/configmap.yaml b/charts/spar/templates/configmap.yaml index 2a195f7487b..98711a46791 100644 --- a/charts/spar/templates/configmap.yaml +++ b/charts/spar/templates/configmap.yaml @@ -33,6 +33,10 @@ data: maxScimTokens: {{ .maxScimTokens }} + {{- if .disabledAPIVersions }} + disabledAPIVersions: {{ .disabledAPIVersions }} + {{- end }} + saml: version: SAML2.0 logLevel: {{ .logLevel }} @@ -43,5 +47,5 @@ data: spSsoUri: {{ .ssoUri }} contacts: -{{ toYaml .contacts | indent 12 }} + {{- toYaml .contacts | nindent 8 }} {{- end }} diff --git a/charts/spar/values.yaml b/charts/spar/values.yaml index f378ebdc961..c2023b66340 100644 --- a/charts/spar/values.yaml +++ b/charts/spar/values.yaml @@ -25,3 +25,6 @@ config: maxttlAuthreq: 7200 maxttlAuthresp: 7200 proxy: {} + # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: + # brig, cannon, cargohold, galley, gundeck, proxy, spar. + # disabledAPIVersions: [ 3 ] From 79371b0eb26935aaabf3f9693e8b4ca009239d2b Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Wed, 4 Jan 2023 17:40:46 +0100 Subject: [PATCH 09/14] Update developer docs: how to run against kube-ci --- docs/src/developer/developer/how-to.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/src/developer/developer/how-to.md b/docs/src/developer/developer/how-to.md index 0ed606399b3..539dcd8c726 100644 --- a/docs/src/developer/developer/how-to.md +++ b/docs/src/developer/developer/how-to.md @@ -2,6 +2,13 @@ The following assume you have a working developer environment with all the dependencies listed in [./dependencies.md](./dependencies.md) available to you. +If you want to deploy to the CI kubernetes cluster (how-tos bewlow) you need set `KUBECONFIG` env var, where `$cailleach_repo` is replaced by your local checkout of the `cailleach` repository. +``` +export KUBECONFIG=$cailleach_repo/environments/kube-ci/kubeconfig.dec +``` +Check that this file exists by running `ls $KUBECONFIG`. + + ## How to look at the swagger docs / UI locally Terminal 1: From 3a78d69c093088efbbbf149c521cfcb27ce5cf1b Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Thu, 5 Jan 2023 10:38:28 +0100 Subject: [PATCH 10/14] Update documentation --- .../src/developer/reference/config-options.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/src/developer/reference/config-options.md b/docs/src/developer/reference/config-options.md index 4fe558e4ad3..98eb07ff178 100644 --- a/docs/src/developer/reference/config-options.md +++ b/docs/src/developer/reference/config-options.md @@ -604,3 +604,37 @@ If there is no configuration for a domain, it's defaulted to `no_search`. #### `setEnableDevelopmentVersions` This options determines whether development versions should be enabled. If set to `False`, all development versions are removed from the `supported` field of the `/api-version` endpoint. Note that they are still listed in the `development` field, and continue to work normally. + +#### Disabling API versions + +It is possible to disable one ore more API versions. When an API version is disabled it won't be advertised on the `GET /api-version` endpoint, neither in the `supported`, nor in the `development` section. Requests made to any endpoint of a disabled API version will result in the same error response as a request made to an API version that does not exist. + +Each of the services brig, cannon, cargohold, galley, gundeck, proxy, spar should to be configured with the same set of disable API versions in each service's values.yaml config files. + + +For example to disable API version v3, you need to configure: + +``` +# brig's values.yaml +config.optSettings.setDisabledAPIVersions: [ 3 ] + +# cannon's values.yaml +config.disabledAPIVersions: [ 3 ] + +# cargohold's values.yaml +config.settings.disabledAPIVersions: [ 3 ] + +# galley's values.yaml +config.settings.disabledAPIVersions: [ 3 ] + +# gundecks' values.yaml +config.disabledAPIVersions: [ 3 ] + +# proxy's values.yaml +config.disabledAPIVersions: [ 3 ] + +# spar's values.yaml +config.disabledAPIVersions: [ 3 ] +``` + +The default setting is that no API version is disabled. From 896cdd96133474a2f72626f5c7c5758cc6239305 Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Thu, 5 Jan 2023 10:43:47 +0100 Subject: [PATCH 11/14] Update example value in cargohold's values.yaml --- charts/cargohold/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/cargohold/values.yaml b/charts/cargohold/values.yaml index 83411e0035e..5445d1bc232 100644 --- a/charts/cargohold/values.yaml +++ b/charts/cargohold/values.yaml @@ -28,7 +28,7 @@ config: downloadLinkTTL: 300 # Seconds # Disable one ore more API versions. Please make sure the configuration value is the same in all these charts: # brig, cannon, cargohold, galley, gundeck, proxy, spar. - # disabledAPIVersions: [ 2 ] + # disabledAPIVersions: [ 3 ] serviceAccount: # When setting this to 'false', either make sure that a service account named From 80c79bf76eef6d7aa170d159fc671166b880b718 Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Thu, 5 Jan 2023 11:29:40 +0100 Subject: [PATCH 12/14] Add changelog entry --- changelog.d/2-features/pr-2951 | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/2-features/pr-2951 diff --git a/changelog.d/2-features/pr-2951 b/changelog.d/2-features/pr-2951 new file mode 100644 index 00000000000..7fe0aeddb98 --- /dev/null +++ b/changelog.d/2-features/pr-2951 @@ -0,0 +1 @@ +Introduce optional disabledAPIVersions configuration setting From 94edcd2c7ffd5dc154221972debd79bbde52db8b Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Thu, 5 Jan 2023 11:29:51 +0100 Subject: [PATCH 13/14] Fix test wording --- services/brig/test/integration/API/Version.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/brig/test/integration/API/Version.hs b/services/brig/test/integration/API/Version.hs index b9e209a39e7..bd4945e879f 100644 --- a/services/brig/test/integration/API/Version.hs +++ b/services/brig/test/integration/API/Version.hs @@ -41,7 +41,7 @@ tests p opts brig = test p "GET /api-version (with dev)" $ testDevVersion opts brig, test p "GET /v500/api-version" $ testUnsupportedVersion brig, test p "GET /api-version (federation info)" $ testFederationDomain opts brig, - test p "Disabled version makes it unsupported" $ testDisabledVersionIsUnsupported opts brig, + test p "Disabled version is unsupported" $ testDisabledVersionIsUnsupported opts brig, test p "Disabled version is not advertised" $ testVersionDisabledSupportedVersion opts brig, test p "Disabled dev version is not advertised" $ testVersionDisabledDevelopmentVersion opts brig ] From 1c3c829a55f177d11eaefe1d8c7f97fc316eee21 Mon Sep 17 00:00:00 2001 From: Stefan Matting Date: Fri, 6 Jan 2023 10:23:39 +0100 Subject: [PATCH 14/14] Update docs/src/developer/developer/how-to.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marko Dimjašević --- docs/src/developer/developer/how-to.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/developer/developer/how-to.md b/docs/src/developer/developer/how-to.md index 539dcd8c726..14c0e278d9b 100644 --- a/docs/src/developer/developer/how-to.md +++ b/docs/src/developer/developer/how-to.md @@ -2,7 +2,7 @@ The following assume you have a working developer environment with all the dependencies listed in [./dependencies.md](./dependencies.md) available to you. -If you want to deploy to the CI kubernetes cluster (how-tos bewlow) you need set `KUBECONFIG` env var, where `$cailleach_repo` is replaced by your local checkout of the `cailleach` repository. +If you want to deploy to the CI kubernetes cluster (how-tos below), you need to set the `KUBECONFIG` env var, where `$cailleach_repo` is replaced by your local checkout of the `cailleach` repository. ``` export KUBECONFIG=$cailleach_repo/environments/kube-ci/kubeconfig.dec ```