Skip to content

Commit cb6e9c2

Browse files
sysvinitsupersvenfisx
authored
Feature flag for exposing invite URLs to team admins [SQPIT-1368] (#2684)
This flag is generally locked and disabled. To be able to unlock/enable it, the team id must be added to the list of eligible teams. The invitation URLs are meant to be used in automatized onboarding processes; e.g. rendering them as QR codes. N.B. getting hold of the invitation URLs makes it possible to impersonate as someone else. That's why there's this two-configs solution: To make sure it's only activated when absolutely needed (and not accidentally.) Co-authored-by: Sven Tennie <[email protected]> Co-authored-by: Molly Miller <[email protected]> Co-authored-by: Matthias Fischmann <[email protected]>
1 parent 9830a3e commit cb6e9c2

File tree

63 files changed

+965
-414
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+965
-414
lines changed

cassandra-schema.cql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ CREATE TABLE galley_test.team_features (
128128
app_lock_status int,
129129
conference_calling int,
130130
digital_signatures int,
131+
expose_invitation_urls_to_team_admin int,
131132
file_sharing int,
132133
file_sharing_lock_status int,
133134
guest_links_lock_status int,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Optionally add invitation urls to the body of `/teams/{tid}/invitations`. This allows further processing; e.g. to send those links with custom emails or distribute them as QR codes. See [docs](https://docs.wire.com/developer/reference/config-options.html#expose-invitation-urls-to-team-admin) for details and privacy implications.

charts/galley/templates/configmap.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ data:
5454
{{- if .settings.maxFanoutSize }}
5555
maxFanoutSize: {{ .settings.maxFanoutSize }}
5656
{{- end }}
57+
{{- if .settings.exposeInvitationURLsTeamAllowlist }}
58+
exposeInvitationURLsTeamAllowlist: {{ .settings.exposeInvitationURLsTeamAllowlist }}
59+
{{- end }}
5760
conversationCodeURI: {{ .settings.conversationCodeURI | quote }}
5861
{{- if .settings.enableIndexedBillingTeamMembers }}
5962
enableIndexedBillingTeamMembers: {{ .settings.enableIndexedBillingTeamMembers }}
@@ -92,15 +95,15 @@ data:
9295
{{- if .settings.featureFlags.appLock }}
9396
appLock:
9497
{{- toYaml .settings.featureFlags.appLock | nindent 10 }}
95-
{{- end }}
98+
{{- end }}
9699
{{- if .settings.featureFlags.conferenceCalling }}
97100
conferenceCalling:
98101
{{- toYaml .settings.featureFlags.conferenceCalling | nindent 10 }}
99-
{{- end }}
102+
{{- end }}
100103
{{- if .settings.featureFlags.selfDeletingMessages }}
101104
selfDeletingMessages:
102105
{{- toYaml .settings.featureFlags.selfDeletingMessages | nindent 10 }}
103-
{{- end }}
106+
{{- end }}
104107
{{- if .settings.featureFlags.conversationGuestLinks }}
105108
conversationGuestLinks:
106109
{{- toYaml .settings.featureFlags.conversationGuestLinks | nindent 10 }}

charts/galley/values.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ config:
2626
settings:
2727
httpPoolSize: 128
2828
maxTeamSize: 10000
29+
exposeInvitationURLsTeamAllowlist: []
2930
maxConvSize: 500
3031
# Before making indexedBillingTeamMember true while upgrading, please
3132
# refer to notes here: https://github.com/wireapp/wire-server-deploy/releases/tag/v2020-05-15
@@ -79,7 +80,7 @@ config:
7980
validateSAMLemails:
8081
defaults:
8182
status: enabled
82-
83+
8384
aws:
8485
region: "eu-west-1"
8586
proxy: {}

docs/src/developer/reference/config-options.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,53 @@ IMPORTANT: If you switch this back to `disabled-permanently` from
9999
that have created them while it was allowed. This may change in the
100100
future.
101101

102+
### Expose invitation URLs to team admin
103+
104+
For further processing (e.g. sending custom emails or rendering the URLs as QR
105+
codes), team invitation URLs can be made part of the result of
106+
`GET /teams/{tid}/invitations`.
107+
108+
```json
109+
{
110+
"has_more": false,
111+
"invitations": [
112+
{
113+
"created_at": "2022-09-15T15:47:28.577Z",
114+
"created_by": "375f56fe-7f12-4c0c-aed8-d48c0326d1fb",
115+
"email": "[email protected]",
116+
"id": "4decf7f8-bdd4-43b3-aaf2-e912e2c0c46f",
117+
"name": null,
118+
"phone": null,
119+
"role": "member",
120+
"team": "51612209-3b61-49b0-8c55-d21ae65efc1a",
121+
"url": "http://127.0.0.1:8080/register?team=51612209-3b61-49b0-8c55-d21ae65efc1a&team_code=RpxGkK_yjw8ZBegJuFQO0hha-2Tneajp"
122+
}
123+
]
124+
}
125+
```
126+
127+
This can be a privacy issue as it allows the team admin to impersonate as
128+
another team member. The feature is disabled by default.
129+
130+
To activate this feature two steps are needed. First, the team id (tid) has to
131+
be added to the list of teams for which this feature *can* be enabled
132+
(`exposeInvitationURLsTeamAllowlist`). This is done in `galley`'s `values.yaml`:
133+
134+
```yaml
135+
settings:
136+
exposeInvitationURLsTeamAllowlist: ["51612209-3b61-49b0-8c55-d21ae65efc1a", ...]
137+
```
138+
139+
Then, the feature can be set for the team by enabling the
140+
`exposeInvitationURLsToTeamAdmin` flag. This is done by making a `PUT` request
141+
to `/teams/{tid}/features/exposeInvitationURLsToTeamAdmin` with the body:
142+
143+
```json
144+
{
145+
"status": "enabled"
146+
}
147+
```
148+
102149
### Team searchVisibility
103150

104151
The team flag `searchVisibility` affects the outbound search of user

libs/wire-api/src/Wire/API/Routes/Public/Galley.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,8 @@ type FeatureAPI =
11361136
:<|> FeatureStatusPut '() SndFactorPasswordChallengeConfig
11371137
:<|> FeatureStatusGet MLSConfig
11381138
:<|> FeatureStatusPut '() MLSConfig
1139+
:<|> FeatureStatusGet ExposeInvitationURLsToTeamAdminConfig
1140+
:<|> FeatureStatusPut '() ExposeInvitationURLsToTeamAdminConfig
11391141
:<|> FeatureStatusGet SearchVisibilityInboundConfig
11401142
:<|> FeatureStatusPut '() SearchVisibilityInboundConfig
11411143
:<|> AllFeatureConfigsUserGet

libs/wire-api/src/Wire/API/Team/Feature.hs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ module Wire.API.Team.Feature
6767
DigitalSignaturesConfig (..),
6868
ConferenceCallingConfig (..),
6969
GuestLinksConfig (..),
70+
ExposeInvitationURLsToTeamAdminConfig (..),
7071
SndFactorPasswordChallengeConfig (..),
7172
SearchVisibilityInboundConfig (..),
7273
ClassifiedDomainsConfig (..),
@@ -579,6 +580,7 @@ allFeatureModels =
579580
withStatusNoLockModel @SndFactorPasswordChallengeConfig,
580581
withStatusNoLockModel @SearchVisibilityInboundConfig,
581582
withStatusNoLockModel @MLSConfig,
583+
withStatusNoLockModel @ExposeInvitationURLsToTeamAdminConfig,
582584
withStatusModel @LegalholdConfig,
583585
withStatusModel @SSOConfig,
584586
withStatusModel @SearchVisibilityAvailableConfig,
@@ -592,7 +594,8 @@ allFeatureModels =
592594
withStatusModel @GuestLinksConfig,
593595
withStatusModel @SndFactorPasswordChallengeConfig,
594596
withStatusModel @SearchVisibilityInboundConfig,
595-
withStatusModel @MLSConfig
597+
withStatusModel @MLSConfig,
598+
withStatusModel @ExposeInvitationURLsToTeamAdminConfig
596599
]
597600
<> catMaybes
598601
[ configModel @LegalholdConfig,
@@ -608,7 +611,8 @@ allFeatureModels =
608611
configModel @GuestLinksConfig,
609612
configModel @SndFactorPasswordChallengeConfig,
610613
configModel @SearchVisibilityInboundConfig,
611-
configModel @MLSConfig
614+
configModel @MLSConfig,
615+
configModel @ExposeInvitationURLsToTeamAdminConfig
612616
]
613617

614618
--------------------------------------------------------------------------------
@@ -939,6 +943,24 @@ instance IsFeatureConfig MLSConfig where
939943
Doc.property "allowedCipherSuites" (Doc.array Doc.int32') $ Doc.description "cipher suite numbers, See https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#table-5"
940944
Doc.property "defaultCipherSuite" Doc.int32' $ Doc.description "cipher suite number. See https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#table-5"
941945

946+
----------------------------------------------------------------------
947+
-- ExposeInvitationURLsToTeamAdminConfig
948+
949+
data ExposeInvitationURLsToTeamAdminConfig = ExposeInvitationURLsToTeamAdminConfig
950+
deriving stock (Show, Eq, Generic)
951+
deriving (Arbitrary) via (GenericUniform ExposeInvitationURLsToTeamAdminConfig)
952+
953+
instance IsFeatureConfig ExposeInvitationURLsToTeamAdminConfig where
954+
type FeatureSymbol ExposeInvitationURLsToTeamAdminConfig = "exposeInvitationURLsToTeamAdmin"
955+
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked ExposeInvitationURLsToTeamAdminConfig FeatureTTLUnlimited
956+
objectSchema = pure ExposeInvitationURLsToTeamAdminConfig
957+
958+
instance ToSchema ExposeInvitationURLsToTeamAdminConfig where
959+
schema = object "ExposeInvitationURLsToTeamAdminConfig" objectSchema
960+
961+
instance FeatureTrivialConfig ExposeInvitationURLsToTeamAdminConfig where
962+
trivialConfig = ExposeInvitationURLsToTeamAdminConfig
963+
942964
----------------------------------------------------------------------
943965
-- FeatureStatus
944966

@@ -1007,7 +1029,8 @@ data AllFeatureConfigs = AllFeatureConfigs
10071029
afcSelfDeletingMessages :: WithStatus SelfDeletingMessagesConfig,
10081030
afcGuestLink :: WithStatus GuestLinksConfig,
10091031
afcSndFactorPasswordChallenge :: WithStatus SndFactorPasswordChallengeConfig,
1010-
afcMLS :: WithStatus MLSConfig
1032+
afcMLS :: WithStatus MLSConfig,
1033+
afcExposeInvitationURLsToTeamAdmin :: WithStatus ExposeInvitationURLsToTeamAdminConfig
10111034
}
10121035
deriving stock (Eq, Show)
10131036
deriving (FromJSON, ToJSON, S.ToSchema) via (Schema AllFeatureConfigs)
@@ -1030,6 +1053,7 @@ instance ToSchema AllFeatureConfigs where
10301053
<*> afcGuestLink .= featureField
10311054
<*> afcSndFactorPasswordChallenge .= featureField
10321055
<*> afcMLS .= featureField
1056+
<*> afcExposeInvitationURLsToTeamAdmin .= featureField
10331057
where
10341058
featureField ::
10351059
forall cfg.
@@ -1054,5 +1078,6 @@ instance Arbitrary AllFeatureConfigs where
10541078
<*> arbitrary
10551079
<*> arbitrary
10561080
<*> arbitrary
1081+
<*> arbitrary
10571082

10581083
makeLenses ''ImplicitLockStatus

libs/wire-api/src/Wire/API/Team/Invitation.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import Data.Id
3434
import Data.Json.Util
3535
import qualified Data.Swagger.Build.Api as Doc
3636
import Imports
37+
import URI.ByteString
3738
import Wire.API.Team.Role (Role, defaultRole, typeRole)
3839
import Wire.API.User.Identity (Email, Phone)
3940
import Wire.API.User.Profile (Locale, Name)
@@ -104,7 +105,8 @@ data Invitation = Invitation
104105
inCreatedBy :: Maybe UserId,
105106
inInviteeEmail :: Email,
106107
inInviteeName :: Maybe Name,
107-
inInviteePhone :: Maybe Phone
108+
inInviteePhone :: Maybe Phone,
109+
inInviteeUrl :: Maybe (URIRef Absolute)
108110
}
109111
deriving stock (Eq, Show, Generic)
110112
deriving (Arbitrary) via (GenericUniform Invitation)
@@ -134,6 +136,9 @@ modelTeamInvitation = Doc.defineModel "TeamInvitation" $ do
134136
Doc.property "phone" Doc.string' $ do
135137
Doc.description "Phone number of the invitee, in the E.164 format"
136138
Doc.optional
139+
Doc.property "url" Doc.string' $ do
140+
Doc.description "URL of the invitation link to be sent to the invitee"
141+
Doc.optional
137142

138143
instance ToJSON Invitation where
139144
toJSON i =
@@ -145,7 +150,8 @@ instance ToJSON Invitation where
145150
"created_by" .= inCreatedBy i,
146151
"email" .= inInviteeEmail i,
147152
"name" .= inInviteeName i,
148-
"phone" .= inInviteePhone i
153+
"phone" .= inInviteePhone i,
154+
"url" .= inInviteeUrl i
149155
]
150156

151157
instance FromJSON Invitation where
@@ -160,6 +166,7 @@ instance FromJSON Invitation where
160166
<*> o .: "email"
161167
<*> o .:? "name"
162168
<*> o .:? "phone"
169+
<*> o .:? "url"
163170

164171
--------------------------------------------------------------------------------
165172
-- InvitationList

0 commit comments

Comments
 (0)