Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cassandra-schema.cql
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ CREATE TABLE galley_test.team_features (
guest_links_lock_status int,
guest_links_status int,
legalhold_status int,
mls_allowed_ciphersuites set<int>,
mls_default_ciphersuite int,
mls_default_protocol int,
mls_protocol_toggle_users set<uuid>,
mls_status int,
search_visibility_inbound_status int,
search_visibility_status int,
self_deleting_messages_lock_status int,
Expand Down
1 change: 1 addition & 0 deletions changelog.d/2-features/pr-2499
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add MLS team feature configuration
4 changes: 4 additions & 0 deletions charts/galley/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,9 @@ data:
searchVisibilityInbound:
{{- toYaml .settings.featureFlags.searchVisibilityInbound | nindent 10 }}
{{- end }}
{{- if .settings.featureFlags.mls }}
mls:
{{- toYaml .settings.featureFlags.mls | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
8 changes: 8 additions & 0 deletions charts/galley/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ config:
lockStatus: unlocked
status: enabled
legalhold: disabled-by-default
mls:
defaults:
status: disabled
config:
protocolToggleUsers: []
defaultProtocol: proteus
allowedCipherSuites: [1]
defaultCipherSuite: 1
searchVisibilityInbound:
defaults:
status: disabled
Expand Down
26 changes: 26 additions & 0 deletions docs/legacy/reference/config-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,32 @@ sndFactorPasswordChallenge:
lockStatus: locked|unlocked
```

### MLS

This feature specifies how should behave. It has no effect on the server's behaviour.

If this feature is enabled then clients that support this feature will allowing its user to switch between Proteus and the MLS protocol provided the user is listed ini `protocolToggleUsers`. The default protocol that clients will create new conversations with is specified in `defaultProtocol`. The `defaultCipherSuite` and `allowedCipherSuites` contain the default ciphersuite and the allowed ciphersuites that clients should be using. The numerical values should correspond to the indices (starting at 1) specified here https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#table-5

If this feature is disabled then clients will use the Proteus protocol with this backend.

The default configuration that applies to all teams that didn't explicitly change their feature configuration can be given in galley's `featureFlags` section in the config file:

```
# galley.yaml
mls:
defaults:
status: disabled
config:
protocolToggleUsers: []
defaultProtocol: proteus
allowedCipherSuites: [1]
defaultCipherSuite: 1

```

This default configuration can be overriden on a per-team basis through the [feature config API](./features.md)


### Federation Domain

Regardless of whether a backend wants to enable federation or not, the operator
Expand Down
9 changes: 7 additions & 2 deletions libs/galley-types/src/Galley/Types/Teams.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module Galley.Types.Teams
flagsTeamFeatureValidateSAMLEmailsStatus,
flagTeamFeatureSndFactorPasswordChallengeStatus,
flagTeamFeatureSearchVisibilityInbound,
flagMLS,
Defaults (..),
ImplicitLockStatus (..),
unImplicitLockStatus,
Expand Down Expand Up @@ -235,7 +236,8 @@ data FeatureFlags = FeatureFlags
_flagConversationGuestLinks :: !(Defaults (WithStatus GuestLinksConfig)),
_flagsTeamFeatureValidateSAMLEmailsStatus :: !(Defaults (ImplicitLockStatus ValidateSAMLEmailsConfig)),
_flagTeamFeatureSndFactorPasswordChallengeStatus :: !(Defaults (WithStatus SndFactorPasswordChallengeConfig)),
_flagTeamFeatureSearchVisibilityInbound :: !(Defaults (ImplicitLockStatus SearchVisibilityInboundConfig))
_flagTeamFeatureSearchVisibilityInbound :: !(Defaults (ImplicitLockStatus SearchVisibilityInboundConfig)),
_flagMLS :: !(Defaults (ImplicitLockStatus MLSConfig))
}
deriving (Eq, Show, Generic)

Expand Down Expand Up @@ -286,6 +288,7 @@ instance FromJSON FeatureFlags where
<*> withImplicitLockStatusOrDefault obj "validateSAMLEmails"
<*> (fromMaybe (Defaults (defFeatureStatus @SndFactorPasswordChallengeConfig)) <$> (obj .:? "sndFactorPasswordChallenge"))
<*> withImplicitLockStatusOrDefault obj "searchVisibilityInbound"
<*> withImplicitLockStatusOrDefault obj "mls"
where
withImplicitLockStatusOrDefault :: forall cfg. (IsFeatureConfig cfg, Schema.ToSchema cfg) => Object -> Key -> A.Parser (Defaults (ImplicitLockStatus cfg))
withImplicitLockStatusOrDefault obj fieldName = fromMaybe (Defaults (ImplicitLockStatus (defFeatureStatus @cfg))) <$> obj .:? fieldName
Expand All @@ -305,6 +308,7 @@ instance ToJSON FeatureFlags where
validateSAMLEmails
sndFactorPasswordChallenge
searchVisibilityInbound
mls
) =
object
[ "sso" .= sso,
Expand All @@ -318,7 +322,8 @@ instance ToJSON FeatureFlags where
"conversationGuestLinks" .= guestLinks,
"validateSAMLEmails" .= validateSAMLEmails,
"sndFactorPasswordChallenge" .= sndFactorPasswordChallenge,
"searchVisibilityInbound" .= searchVisibilityInbound
"searchVisibilityInbound" .= searchVisibilityInbound,
"mls" .= mls
]

instance FromJSON FeatureSSO where
Expand Down
1 change: 1 addition & 0 deletions libs/galley-types/test/unit/Test/Galley/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ instance Arbitrary FeatureFlags where
<*> fmap (fmap unlocked) arbitrary
<*> arbitrary
<*> fmap (fmap unlocked) arbitrary
<*> fmap (fmap unlocked) arbitrary
where
unlocked :: ImplicitLockStatus a -> ImplicitLockStatus a
unlocked = ImplicitLockStatus . setUnlocked . _unImplicitLockStatus
Expand Down
34 changes: 33 additions & 1 deletion libs/wire-api/src/Wire/API/MLS/CipherSuite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@

module Wire.API.MLS.CipherSuite where

import Control.Lens ((?~))
import Crypto.Error
import Crypto.Hash.Algorithms
import qualified Crypto.KDF.HKDF as HKDF
import qualified Crypto.PubKey.Ed25519 as Ed25519
import Data.Aeson (parseJSON, toJSON)
import Data.Proxy
import Data.Schema
import qualified Data.Swagger as S
import qualified Data.Swagger.Internal.Schema as S
import Data.Word
import Imports
import Wire.API.Arbitrary
Expand All @@ -35,14 +41,40 @@ newtype CipherSuite = CipherSuite {cipherSuiteNumber :: Word16}
deriving newtype (ParseMLS, Arbitrary)

data CipherSuiteTag = MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
deriving stock (Bounded, Enum, Eq, Show)
deriving stock (Bounded, Enum, Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform CipherSuiteTag)

instance S.ToSchema CipherSuiteTag where
declareNamedSchema _ =
pure . S.named "CipherSuiteTag" $
( S.paramSchemaToSchema (Proxy @Word16)
& S.description ?~ "Index number of ciphersuite. See https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#table-5"
)

instance ToSchema CipherSuiteTag where
schema =
mkSchema
(swaggerDoc @CipherSuiteTag)
tagParser
(Just . toJSON . cipherSuiteNumber . tagCipherSuite)
where
tagParser v = do
index <- parseJSON v
maybe
(fail "Not a valid index number of a ciphersuite. See https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#table-5.")
pure
(cipherSuiteTag (CipherSuite index))

-- | See https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#table-5.
cipherSuiteTag :: CipherSuite -> Maybe CipherSuiteTag
cipherSuiteTag (CipherSuite n) = case n of
1 -> pure MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
_ -> Nothing

-- | Inverse of 'cipherSuiteTag'
tagCipherSuite :: CipherSuiteTag -> CipherSuite
tagCipherSuite MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 = CipherSuite 1

csHash :: CipherSuiteTag -> ByteString -> ByteString -> ByteString
csHash MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 ctx value =
HKDF.expand (HKDF.extract @SHA256 (mempty :: ByteString) value) ctx 16
Expand Down
3 changes: 3 additions & 0 deletions libs/wire-api/src/Wire/API/Routes/Public/Galley.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,8 @@ type FeatureAPI =
:<|> FeatureStatusPut '() GuestLinksConfig
:<|> FeatureStatusGet SndFactorPasswordChallengeConfig
:<|> FeatureStatusPut '() SndFactorPasswordChallengeConfig
:<|> FeatureStatusGet MLSConfig
:<|> FeatureStatusPut '() MLSConfig
:<|> AllFeatureConfigsUserGet
:<|> AllFeatureConfigsTeamGet
:<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is not used by team management, or webapp, and is potentially used by the old Android client as of June 2022" LegalholdConfig
Expand All @@ -1132,6 +1134,7 @@ type FeatureAPI =
:<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is not used by team management, or webapp, and is potentially used by the old Android client as of June 2022" SelfDeletingMessagesConfig
:<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is used by team management, webapp, and potentially the old Android client as of June 2022" GuestLinksConfig
:<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is used by team management, webapp, and potentially the old Android client as of June 2022" SndFactorPasswordChallengeConfig
:<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is used by team management, webapp, and potentially the old Android client as of June 2022" MLSConfig

type FeatureStatusGet f =
Named
Expand Down
Loading