-
Notifications
You must be signed in to change notification settings - Fork 325
/
Options.hs
178 lines (160 loc) · 7.02 KB
/
Options.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- 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 CargoHold.Options where
import Amazonka (S3AddressingStyle (..))
import qualified CargoHold.CloudFront as CF
import Control.Lens hiding (Level)
import Data.Aeson (FromJSON (..), withText)
import Data.Aeson.TH
import Data.Domain
import Imports
import System.Logger.Extended (Level, LogFormat)
import Util.Options
import Util.SuffixNamer
import Wire.API.Routes.Version
-- | AWS CloudFront settings.
data CloudFrontOpts = CloudFrontOpts
{ -- | Domain
domain :: CF.Domain,
-- | Keypair ID
keyPairId :: CF.KeyPairId,
-- | Path to private key
privateKey :: FilePath
}
deriving (Show, Generic)
deriveFromJSON defaultOptions ''CloudFrontOpts
newtype OptS3AddressingStyle = OptS3AddressingStyle
{ unwrapS3AddressingStyle :: S3AddressingStyle
}
deriving (Show)
instance FromJSON OptS3AddressingStyle where
parseJSON =
withText "S3AddressingStyle" $
fmap OptS3AddressingStyle . \case
"auto" -> pure S3AddressingStyleAuto
"path" -> pure S3AddressingStylePath
"virtual" -> pure S3AddressingStyleVirtual
other -> fail $ "invalid S3AddressingStyle: " <> show other
data AWSOpts = AWSOpts
{ s3Endpoint :: !AWSEndpoint,
-- | S3 can either by addressed in path style, i.e.
-- https://<s3-endpoint>/<bucket-name>/<object>, or vhost style, i.e.
-- https://<bucket-name>.<s3-endpoint>/<object>. AWS's S3 offering has
-- deprecated path style addressing for S3 and completely disabled it for
-- buckets created after 30 Sep 2020:
-- https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/
--
-- However other object storage providers (specially self-deployed ones like
-- MinIO) may not support vhost style addressing yet (or ever?). Users of
-- such buckets should configure this option to "path".
--
-- Installations using S3 service provided by AWS, should use "auto", this
-- option will ensure that vhost style is only used when it is possible to
-- construct a valid hostname from the bucket name and the bucket name
-- doesn't contain a '.'. Having a '.' in the bucket name causes TLS
-- validation to fail, hence it is not used by default.
--
-- Using "virtual" as an option is only useful in situations where vhost
-- style addressing must be used even if it is not possible to construct a
-- valid hostname from the bucket name or the S3 service provider can ensure
-- correct certificate is issued for bucket which contain one or more '.'s
-- in the name.
--
-- When this option is unspecified, we default to path style addressing to
-- ensure smooth transition for older deployments.
s3AddressingStyle :: !(Maybe OptS3AddressingStyle),
-- | S3 endpoint for generating download links. Useful if Cargohold is configured to use
-- an S3 replacement running inside the internal network (in which case internally we
-- would use one hostname for S3, and when generating an asset link for a client app, we
-- would use another hostname).
s3DownloadEndpoint :: !(Maybe AWSEndpoint),
-- | S3 bucket name
s3Bucket :: !Text,
-- | Enable this option for compatibility with specific S3 backends.
s3Compatibility :: !(Maybe S3Compatibility),
-- | AWS CloudFront options
cloudFront :: !(Maybe CloudFrontOpts),
-- | @Z-Host@ header to s3 download endpoint `Map`
--
-- This logic is: If the @Z-Host@ header is provided and found in this map,
-- the map's values is taken as s3 download endpoint to redirect to;
-- otherwise a 404 is retuned. This option is only useful
-- in the context of multi-ingress setups where one backend / deployment is
-- reachable under several domains.
multiIngress :: !(Maybe (Map String AWSEndpoint))
}
deriving (Show, Generic)
data S3Compatibility
= -- | Scality RING, might also work for Zenko CloudServer
-- <https://www.scality.com/products/ring/>
S3CompatibilityScalityRing
deriving (Eq, Show)
instance FromJSON S3Compatibility where
parseJSON = withText "S3Compatibility" $ \case
"scality-ring" -> pure S3CompatibilityScalityRing
other -> fail $ "invalid S3Compatibility: " <> show other
deriveFromJSON defaultOptions ''AWSOpts
makeLensesFor
[ ("multiIngress", "multiIngressLens"),
("s3DownloadEndpoint", "s3DownloadEndpointLens"),
("cloudFront", "cloudFrontLens")
]
''AWSOpts
data Settings = Settings
{ -- | Maximum allowed size for uploads, in bytes
maxTotalBytes :: !Int,
-- | TTL for download links, in seconds
downloadLinkTTL :: !Word,
-- | FederationDomain is required, even when not wanting to federate with other backends
-- (in that case the 'allowedDomains' can be set to empty in Federator)
-- Federation domain is used to qualify local IDs and handles,
-- e.g. 0c4d8944-70fa-480e-a8b7-9d929862d18c@wire.com and somehandle@wire.com.
-- It should also match the SRV DNS records under which other wire-server installations can find this backend:
-- _wire-server-federator._tcp.<federationDomain>
-- Once set, DO NOT change it: if you do, existing users may have a broken experience and/or stop working
-- Remember to keep it the same in all services.
-- 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
federationDomain :: !Domain,
disabledAPIVersions :: !(Set VersionExp)
}
deriving (Show, Generic)
deriveFromJSON defaultOptions ''Settings
-- | Options consist of information the server needs to operate, and 'Settings'
-- modify the behavior.
data Opts = Opts
{ -- | Hostname and port to bind to
cargohold :: !Endpoint,
aws :: !AWSOpts,
settings :: !Settings,
-- | Federator endpoint
federator :: Maybe Endpoint,
-- | Brig endpoint
brig :: !Endpoint,
-- Logging
-- | Log level (Debug, Info, etc)
logLevel :: !Level,
-- | Use netstrings encoding:
-- <http://cr.yp.to/proto/netstrings.txt>
logNetStrings :: !(Maybe (Last Bool)),
logFormat :: !(Maybe (Last LogFormat)) --- ^ Log format
}
deriving (Show, Generic)
deriveFromJSON defaultOptions ''Opts
makeLensesWith (lensRules & lensField .~ suffixNamer) ''Opts