From fec9e3dc70faada4cc9d98791fd3024bab730328 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 10 Aug 2020 17:59:19 +0100 Subject: [PATCH] HJSON configuration --- cmd/generate-config/main.go | 25 +++++++- go.mod | 3 +- go.sum | 4 +- internal/config/config.go | 69 +++++++++------------- internal/config/config_appservice.go | 36 ++++++----- internal/config/config_clientapi.go | 59 ++++++------------ internal/config/config_currentstate.go | 11 ++-- internal/config/config_eduserver.go | 6 +- internal/config/config_federationapi.go | 19 ++---- internal/config/config_federationsender.go | 34 ++++------- internal/config/config_global.go | 66 ++++++--------------- internal/config/config_kafka.go | 16 ++--- internal/config/config_keyserver.go | 9 ++- internal/config/config_mediaapi.go | 37 ++++-------- internal/config/config_roomserver.go | 9 ++- internal/config/config_serverkey.go | 39 ++++++++---- internal/config/config_syncapi.go | 9 ++- internal/config/config_userapi.go | 15 ++--- internal/httputil/httpapi.go | 8 +-- internal/httputil/httpapi_test.go | 14 +++-- 20 files changed, 197 insertions(+), 291 deletions(-) diff --git a/cmd/generate-config/main.go b/cmd/generate-config/main.go index 4dd125933..83a3508e3 100644 --- a/cmd/generate-config/main.go +++ b/cmd/generate-config/main.go @@ -3,8 +3,8 @@ package main import ( "fmt" + "github.com/hjson/hjson-go" "github.com/matrix-org/dendrite/internal/config" - "gopkg.in/yaml.v2" ) func main() { @@ -19,8 +19,29 @@ func main() { }, }, } + /* + - server_name: matrix.org + keys: + - key_id: ed25519:auto + public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw + - key_id: ed25519:a_RXGa + public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ + */ + cfg.ServerKeyAPI.KeyPerspectives = append(cfg.ServerKeyAPI.KeyPerspectives, config.KeyPerspective{ + ServerName: "matrix.org", + Keys: []config.KeyPerspectiveTrustKeys{ + { + KeyID: "ed25519:auto", + PublicKey: "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw", + }, + { + KeyID: "ed25519:a_RXGa", + PublicKey: "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ", + }, + }, + }) - j, err := yaml.Marshal(cfg) + j, err := hjson.Marshal(cfg) if err != nil { panic(err) } diff --git a/go.mod b/go.mod index d5cf91713..96be863a4 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,11 @@ module github.com/matrix-org/dendrite require ( github.com/Shopify/sarama v1.26.1 - github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect - github.com/ghodss/yaml v1.0.0 github.com/gologme/log v1.2.0 github.com/gorilla/mux v1.7.3 github.com/hashicorp/golang-lru v0.5.4 + github.com/hjson/hjson-go v3.0.2-0.20200316202735-d5d0e8b0617d+incompatible github.com/lib/pq v1.2.0 github.com/libp2p/go-libp2p v0.6.0 github.com/libp2p/go-libp2p-circuit v0.1.4 diff --git a/go.sum b/go.sum index 8ed62ffd6..27d1a0de7 100644 --- a/go.sum +++ b/go.sum @@ -51,9 +51,6 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw= -github.com/circonus-labs/circonus-gometrics v1.2.0 h1:Kqa/+nIJhqFJ12B07aeekgC6F95J7yYgEtpD57NQzrE= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -175,6 +172,7 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hjson/hjson-go v3.0.2-0.20200316202735-d5d0e8b0617d+incompatible h1:v6BPcb9q9U6JDVsuizxBr/piVB/2Y1Q5GWoBybvZVWI= github.com/hjson/hjson-go v3.0.2-0.20200316202735-d5d0e8b0617d+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= diff --git a/internal/config/config.go b/internal/config/config.go index cf9168f71..38b84e8b5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -48,35 +48,35 @@ type Dendrite struct { // to update their config file to the current version. // The version of the file should only be different if there has // been a breaking change to the config file format. - Version int `yaml:"version"` + Version int `json:"Version"` - Global Global `yaml:"global"` - AppServiceAPI AppServiceAPI `yaml:"app_service_api"` - ClientAPI ClientAPI `yaml:"client_api"` - CurrentStateServer CurrentStateServer `yaml:"current_state_server"` - EDUServer EDUServer `yaml:"edu_server"` - FederationAPI FederationAPI `yaml:"federation_api"` - FederationSender FederationSender `yaml:"federation_sender"` - KeyServer KeyServer `yaml:"key_server"` - MediaAPI MediaAPI `yaml:"media_api"` - RoomServer RoomServer `yaml:"room_server"` - ServerKeyAPI ServerKeyAPI `yaml:"server_key_api"` - SyncAPI SyncAPI `yaml:"sync_api"` - UserAPI UserAPI `yaml:"user_api"` + Global Global `json:"Global"` + AppServiceAPI AppServiceAPI `json:"AppServiceAPI"` + ClientAPI ClientAPI `json:"ClientAPI"` + CurrentStateServer CurrentStateServer `json:"CurrentStateServer"` + EDUServer EDUServer `json:"EDUServer"` + FederationAPI FederationAPI `json:"FederationAPI"` + FederationSender FederationSender `json:"FederationSender"` + KeyServer KeyServer `json:"KeyServer"` + MediaAPI MediaAPI `json:"MediaAPI"` + RoomServer RoomServer `json:"RoomServer"` + ServerKeyAPI ServerKeyAPI `json:"ServerKeyAPI"` + SyncAPI SyncAPI `json:"SyncAPI"` + UserAPI UserAPI `json:"UserAPI"` // The config for tracing the dendrite servers. Tracing struct { // Set to true to enable tracer hooks. If false, no tracing is set up. - Enabled bool `yaml:"enabled"` + Enabled bool `json:"Enabled"` // The config for the jaeger opentracing reporter. - Jaeger jaegerconfig.Configuration `yaml:"jaeger"` - } `yaml:"tracing"` + Jaeger jaegerconfig.Configuration `json:"Jaeger"` + } `json:"Tracing"` // The config for logging informations. Each hook will be added to logrus. - Logging []LogrusHook `yaml:"logging"` + Logging []LogrusHook `json:"Logging"` // Any information derived from the configuration options for later use. - Derived Derived `yaml:"-"` + Derived Derived `json:"-"` } // TODO: Kill Derived @@ -86,11 +86,11 @@ type Derived struct { // http://matrix.org/docs/spec/HEAD/client_server/r0.3.0.html#user-interactive-authentication-api // As long as the generated flows only rely on config file options, // we can generate them on startup and store them until needed - Flows []authtypes.Flow `json:"flows"` + Flows []authtypes.Flow `json:"Flows"` // Params that need to be returned to the client during // registration in order to complete registration stages. - Params map[string]interface{} `json:"params"` + Params map[string]interface{} `json:"Params"` } // Application services parsed from their config files @@ -110,21 +110,6 @@ type Derived struct { // servers from creating RoomIDs in exclusive application service namespaces } -// KeyPerspectives are used to configure perspective key servers for -// retrieving server keys. -type KeyPerspectives []struct { - // The server name of the perspective key server - ServerName gomatrixserverlib.ServerName `yaml:"server_name"` - // Server keys for the perspective user, used to verify the - // keys have been signed by the perspective server - Keys []struct { - // The key ID, e.g. ed25519:auto - KeyID gomatrixserverlib.KeyID `yaml:"key_id"` - // The public key in base64 unpadded format - PublicKey string `yaml:"public_key"` - } `yaml:"keys"` -} - // A Path on the filesystem. type Path string @@ -153,13 +138,13 @@ type FileSizeBytes int64 // ThumbnailSize contains a single thumbnail size configuration type ThumbnailSize struct { // Maximum width of the thumbnail image - Width int `yaml:"width"` + Width int `json:"Width"` // Maximum height of the thumbnail image - Height int `yaml:"height"` + Height int `json:"Height"` // ResizeMethod is one of crop or scale. // crop scales to fill the requested dimensions and crops the excess. // scale scales to fit the requested dimensions and one dimension may be smaller than requested. - ResizeMethod string `yaml:"method,omitempty"` + ResizeMethod string `json:"Method,omitempty"` } // LogrusHook represents a single logrus hook. At this point, only parsing and @@ -167,13 +152,13 @@ type ThumbnailSize struct { // Validity/integrity checks on the parameters are done when configuring logrus. type LogrusHook struct { // The type of hook, currently only "file" is supported. - Type string `yaml:"type"` + Type string `json:"Type"` // The level of the logs to produce. Will output only this level and above. - Level string `yaml:"level"` + Level string `json:"Level"` // The parameters for this hook. - Params map[string]interface{} `yaml:"params"` + Params map[string]interface{} `json:"Params"` } // ConfigErrors stores problems encountered when parsing a config file. diff --git a/internal/config/config_appservice.go b/internal/config/config_appservice.go index b8962dedb..68845fb57 100644 --- a/internal/config/config_appservice.go +++ b/internal/config/config_appservice.go @@ -26,15 +26,13 @@ import ( ) type AppServiceAPI struct { - Matrix *Global `yaml:"-"` - Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit + Matrix *Global `json:"-"` + Derived *Derived `json:"-"` // TODO: Nuke Derived from orbit - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - Database DatabaseOptions `yaml:"database"` - - ConfigFiles []string `yaml:"config_files"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database options for this component."` + ConfigFiles []string `json:"ConfigFiles" comment:"List of paths to appservice configuration files."` } func (c *AppServiceAPI) Defaults() { @@ -54,9 +52,9 @@ func (c *AppServiceAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { // service has management over. type ApplicationServiceNamespace struct { // Whether or not the namespace is managed solely by this application service - Exclusive bool `yaml:"exclusive"` + Exclusive bool `json:"Exclusive"` // A regex pattern that represents the namespace - Regex string `yaml:"regex"` + Regex string `json:"Regex"` // The ID of an existing group that all users of this application service will // be added to. This field is only relevant to the `users` namespace. // Note that users who are joined to this group through an application service @@ -64,7 +62,7 @@ type ApplicationServiceNamespace struct { // group should be listed when querying an application service user's groups. // This is to prevent making spamming all users of an application service // trivial. - GroupID string `yaml:"group_id"` + GroupID string `json:"GroupID"` // Regex object representing our pattern. Saves having to recompile every time RegexpObject *regexp.Regexp } @@ -73,22 +71,22 @@ type ApplicationServiceNamespace struct { // https://matrix.org/docs/spec/application_service/unstable.html type ApplicationService struct { // User-defined, unique, persistent ID of the application service - ID string `yaml:"id"` + ID string `json:"ID"` // Base URL of the application service - URL string `yaml:"url"` + URL string `json:"URL"` // Application service token provided in requests to a homeserver - ASToken string `yaml:"as_token"` + ASToken string `json:"ASToken"` // Homeserver token provided in requests to an application service - HSToken string `yaml:"hs_token"` + HSToken string `json:"HSToken"` // Localpart of application service user - SenderLocalpart string `yaml:"sender_localpart"` + SenderLocalpart string `json:"SenderLocalpart"` // Information about an application service's namespaces. Key is either // "users", "aliases" or "rooms" - NamespaceMap map[string][]ApplicationServiceNamespace `yaml:"namespaces"` + NamespaceMap map[string][]ApplicationServiceNamespace `json:"Namespaces"` // Whether rate limiting is applied to each application service user - RateLimited bool `yaml:"rate_limited"` + RateLimited bool `json:"RateLimited"` // Any custom protocols that this application service provides (e.g. IRC) - Protocols []string `yaml:"protocols"` + Protocols []string `json:"Protocols"` } // IsInterestedInRoomID returns a bool on whether an application service's diff --git a/internal/config/config_clientapi.go b/internal/config/config_clientapi.go index c441a9c0b..aadf06aea 100644 --- a/internal/config/config_clientapi.go +++ b/internal/config/config_clientapi.go @@ -6,33 +6,19 @@ import ( ) type ClientAPI struct { - Matrix *Global `yaml:"-"` - Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit + Matrix *Global `json:"-"` + Derived *Derived `json:"-"` // TODO: Nuke Derived from orbit - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // If set, allows registration by anyone who also has the shared - // secret, even if registration is otherwise disabled. - RegistrationSharedSecret string `yaml:"registration_shared_secret"` - // This Home Server's ReCAPTCHA public key. - RecaptchaPublicKey string `yaml:"recaptcha_public_key"` - // This Home Server's ReCAPTCHA private key. - RecaptchaPrivateKey string `yaml:"recaptcha_private_key"` - // Boolean stating whether catpcha registration is enabled - // and required - RecaptchaEnabled bool `yaml:"enable_registration_captcha"` - // Secret used to bypass the captcha registration entirely - RecaptchaBypassSecret string `yaml:"captcha_bypass_secret"` - // HTTP API endpoint used to verify whether the captcha response - // was successful - RecaptchaSiteVerifyAPI string `yaml:"recaptcha_siteverify_api"` - // If set disables new users from registering (except via shared - // secrets) - RegistrationDisabled bool `yaml:"registration_disabled"` - - // TURN options - TURN TURN `yaml:"turn"` + Listen Address `json:"listen" comment:"The listen address for this component."` + Bind Address `json:"bind" comment:"The bind address for this component."` + RegistrationDisabled bool `json:"RegistrationDisabled" comment:"Prevent new users from registering, except when using the shared secret from the\nRegistrationSharedSecret option below."` + RegistrationSharedSecret string `json:"RegistrationSharedSecret" comment:"If set, allows registration by anyone who knows the shared secret, even if\nregistration is otherwise disabled."` + RecaptchaEnabled bool `json:"RecaptchaEnabled" comment:"Whether to require ReCAPTCHA for registration."` + RecaptchaPublicKey string `json:"RecaptchaPublicKey" comment:"This server's ReCAPTCHA public key."` + RecaptchaPrivateKey string `json:"RecaptchaPrivateKey" comment:"This server's ReCAPTCHA private key."` + RecaptchaBypassSecret string `json:"RecaptchaBypassSecret" comment:"Secret used to bypass ReCAPTCHA entirely."` + RecaptchaSiteVerifyAPI string `json:"RecaptchaSiteVerifyAPI" comment:"The URL to use for verifying if the ReCAPTCHA response was successful."` + TURN TURN `json:"TURN"` } func (c *ClientAPI) Defaults() { @@ -59,22 +45,13 @@ func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { } type TURN struct { + UserLifetime string `json:"UserLifetime" comment:"How long the TURN authorisation should last."` + URIs []string `json:"URIs" comment:"The list of TURN URIs to pass to clients."` + SharedSecret string `json:"SharedSecret" comment:"Authorisation shared secret from coturn."` + Username string `json:"Username" comment:"Authorisation static username."` + Password string `json:"Password" comment:"Authorisation static password."` // TODO Guest Support - // Whether or not guests can request TURN credentials - // AllowGuests bool `yaml:"turn_allow_guests"` - // How long the authorization should last - UserLifetime string `yaml:"turn_user_lifetime"` - // The list of TURN URIs to pass to clients - URIs []string `yaml:"turn_uris"` - - // Authorization via Shared Secret - // The shared secret from coturn - SharedSecret string `yaml:"turn_shared_secret"` - - // Authorization via Static Username & Password - // Hardcoded Username and Password - Username string `yaml:"turn_username"` - Password string `yaml:"turn_password"` + // AllowGuests bool `json:"AllowGuests" comment:"Whether or not guests can request TURN credentials."` } func (c *TURN) Verify(configErrs *ConfigErrors) { diff --git a/internal/config/config_currentstate.go b/internal/config/config_currentstate.go index 2687f7f5f..2f47b19e9 100644 --- a/internal/config/config_currentstate.go +++ b/internal/config/config_currentstate.go @@ -1,14 +1,11 @@ package config type CurrentStateServer struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // The CurrentState database stores the current state of all rooms. - // It is accessed by the CurrentStateServer. - Database DatabaseOptions `yaml:"database"` + Listen Address `json:"listen" comment:"Listen address for this component."` + Bind Address `json:"bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` } func (c *CurrentStateServer) Defaults() { diff --git a/internal/config/config_eduserver.go b/internal/config/config_eduserver.go index 027430415..c8001c778 100644 --- a/internal/config/config_eduserver.go +++ b/internal/config/config_eduserver.go @@ -1,10 +1,10 @@ package config type EDUServer struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` } func (c *EDUServer) Defaults() { diff --git a/internal/config/config_federationapi.go b/internal/config/config_federationapi.go index d155ef254..e7dfbf76c 100644 --- a/internal/config/config_federationapi.go +++ b/internal/config/config_federationapi.go @@ -3,21 +3,12 @@ package config import "github.com/matrix-org/gomatrixserverlib" type FederationAPI struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // List of paths to X509 certificates used by the external federation listeners. - // These are used to calculate the TLS fingerprints to publish for this server. - // Other matrix servers talking to this server will expect the x509 certificate - // to match one of these certificates. - // The certificates should be in PEM format. - FederationCertificatePaths []Path `yaml:"federation_certificates"` - - // A list of SHA256 TLS fingerprints for the X509 certificates used by the - // federation listener for this server. - TLSFingerPrints []gomatrixserverlib.TLSFingerprint `yaml:"-"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + FederationCertificatePaths []Path `json:"FederationCertificates" comment:"List of paths to X.509 certificates to be used by the external federation listeners.\nThese certificates will be used to calculate the TLS fingerprints and other servers\nwill expect the certificate to match these fingerprints. Certificates must be in PEM\nformat."` + TLSFingerPrints []gomatrixserverlib.TLSFingerprint `json:"-"` } func (c *FederationAPI) Defaults() { diff --git a/internal/config/config_federationsender.go b/internal/config/config_federationsender.go index 09d8287ba..c4da29ae6 100644 --- a/internal/config/config_federationsender.go +++ b/internal/config/config_federationsender.go @@ -1,26 +1,14 @@ package config type FederationSender struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // The FederationSender database stores information used by the FederationSender - // It is only accessed by the FederationSender. - Database DatabaseOptions `yaml:"database"` - - // Federation failure threshold. How many consecutive failures that we should - // tolerate when sending federation requests to a specific server. The backoff - // is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds, etc. - // The default value is 16 if not specified, which is circa 18 hours. - FederationMaxRetries uint32 `yaml:"send_max_retries"` - - // FederationDisableTLSValidation disables the validation of X.509 TLS certs - // on remote federation endpoints. This is not recommended in production! - DisableTLSValidation bool `yaml:"disable_tls_validation"` - - Proxy Proxy `yaml:"proxy_outbound"` + Listen Address `json:"listen"` + Bind Address `json:"bind"` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` + FederationMaxRetries uint32 `json:"SendMaxRetries" comment:"How many times we will try to resend a failed transaction to a specific server. The\nbackoff is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds etc."` + DisableTLSValidation bool `json:"DisableTLSValidation" comment:"Disable the validation of TLS certificates of remote federated homeservers. Do not\nenable this option in production as it presents a security risk!"` + Proxy Proxy `json:"ProxyOutbound" comment:"Use the following proxy server for outbound federation traffic."` } func (c *FederationSender) Defaults() { @@ -44,13 +32,13 @@ func (c *FederationSender) Verify(configErrs *ConfigErrors, isMonolith bool) { // The config for setting a proxy to use for server->server requests type Proxy struct { // Is the proxy enabled? - Enabled bool `yaml:"enabled"` + Enabled bool `json:"Enabled"` // The protocol for the proxy (http / https / socks5) - Protocol string `yaml:"protocol"` + Protocol string `json:"Protocol"` // The host where the proxy is listening - Host string `yaml:"host"` + Host string `json:"Host"` // The port on which the proxy is listening - Port uint16 `yaml:"port"` + Port uint16 `json:"Port"` } func (c *Proxy) Defaults() { diff --git a/internal/config/config_global.go b/internal/config/config_global.go index 785a8033c..ccbfb9c34 100644 --- a/internal/config/config_global.go +++ b/internal/config/config_global.go @@ -9,36 +9,14 @@ import ( ) type Global struct { - // The name of the server. This is usually the domain name, e.g 'matrix.org', 'localhost'. - ServerName gomatrixserverlib.ServerName `yaml:"server_name"` - - // Path to the private key which will be used to sign requests and events. - PrivateKeyPath Path `yaml:"private_key"` - - // The private key which will be used to sign requests and events. - PrivateKey ed25519.PrivateKey `yaml:"-"` - - // An arbitrary string used to uniquely identify the PrivateKey. Must start with the - // prefix "ed25519:". - KeyID gomatrixserverlib.KeyID `yaml:"-"` - - // How long a remote server can cache our server key for before requesting it again. - // Increasing this number will reduce the number of requests made by remote servers - // for our key, but increases the period a compromised key will be considered valid - // by remote servers. - // Defaults to 24 hours. - KeyValidityPeriod time.Duration `yaml:"key_validity_period"` - - // List of domains that the server will trust as identity servers to - // verify third-party identifiers. - // Defaults to an empty array. - TrustedIDServers []string `yaml:"trusted_third_party_id_servers"` - - // Kafka/Naffka configuration - Kafka Kafka `yaml:"kafka"` - - // Metrics configuration - Metrics Metrics `yaml:"metrics"` + ServerName gomatrixserverlib.ServerName `json:"ServerName" comment:"The domain name of this homeserver."` + PrivateKeyPath Path `json:"PrivateKeyPath" comment:"The path to the signing private key file, used to sign requests and events."` + PrivateKey ed25519.PrivateKey `json:"-"` + KeyID gomatrixserverlib.KeyID `json:"KeyID" comment:"A unique identifier for this private key. Must start with the prefix \"ed25519:\"."` + KeyValidityPeriod time.Duration `json:"KeyValidityPeriod" comment:"How long a remote server can cache our server signing key before requesting it\nagain. Increasing this number will reduce the number of requests made by other\nservers for our key but increases the period that a compromised key will be\nconsidered valid by other homeservers."` + TrustedIDServers []string `json:"TrustedIDServers" comment:"Lists of domains that the server will trust as identity servers to verify third\nparty identifiers such as phone numbers and email addresses."` + Kafka Kafka `json:"Kafka" comment:"Configuration for Kaffka/Naffka."` + Metrics Metrics `json:"Metrics" comment:"Configuration for Prometheus metric collection."` } func (c *Global) Defaults() { @@ -60,17 +38,15 @@ func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) { c.Metrics.Verify(configErrs, isMonolith) } +type BasicAuth struct { + Username string `json:"Username"` + Password string `json:"Password"` +} + // The configuration to use for Prometheus metrics type Metrics struct { - // Whether or not the metrics are enabled - Enabled bool `yaml:"enabled"` - // Use BasicAuth for Authorization - BasicAuth struct { - // Authorization via Static Username & Password - // Hardcoded Username and Password - Username string `yaml:"username"` - Password string `yaml:"password"` - } `yaml:"basic_auth"` + Enabled bool `json:"Enabled" comment:"Whether or not Prometheus metrics are enabled."` + BasicAuth BasicAuth `json:"BasicAuth" comment:"HTTP basic authentication to protect access to monitoring."` } func (c *Metrics) Defaults() { @@ -83,14 +59,10 @@ func (c *Metrics) Verify(configErrs *ConfigErrors, isMonolith bool) { } type DatabaseOptions struct { - // The connection string, file:filename.db or postgres://server.... - ConnectionString DataSource `yaml:"connection_string"` - // Maximum open connections to the DB (0 = use default, negative means unlimited) - MaxOpenConnections int `yaml:"max_open_conns"` - // Maximum idle connections to the DB (0 = use default, negative means unlimited) - MaxIdleConnections int `yaml:"max_idle_conns"` - // maximum amount of time (in seconds) a connection may be reused (<= 0 means unlimited) - ConnMaxLifetimeSeconds int `yaml:"conn_max_lifetime"` + ConnectionString DataSource `json:"ConnectionString" comment:"Connection string, e.g. file:filename.db or postgresql://user:pass@host/db etc."` + MaxOpenConnections int `json:"MaxOpenConnections" comment:"Maximum number of connections to open to the database (0 = use default,\nnegative = unlimited)."` + MaxIdleConnections int `json:"MaxIdleConnections" comment:"Maximum number of idle connections permitted to the database (0 = use default,\nnegative = unlimited)."` + ConnMaxLifetimeSeconds int `json:"ConnMaxLifetimeSeconds" comment:"Maximum amount of time, in seconds, that a database connection may be reused\n(negative = unlimited)."` } func (c *DatabaseOptions) Defaults() { diff --git a/internal/config/config_kafka.go b/internal/config/config_kafka.go index 43a27cf29..4980d551f 100644 --- a/internal/config/config_kafka.go +++ b/internal/config/config_kafka.go @@ -12,18 +12,10 @@ const ( ) type Kafka struct { - // A list of kafka addresses to connect to. - Addresses []string `yaml:"addresses"` - // Whether to use naffka instead of kafka. - // Naffka can only be used when running dendrite as a single monolithic server. - // Kafka can be used both with a monolithic server and when running the - // components as separate servers. - UseNaffka bool `yaml:"use_naffka"` - // The Naffka database is used internally by the naffka library, if used. - Database DatabaseOptions `yaml:"naffka_database"` - // The prefix to use for Kafka topic names for this homeserver - really only - // useful if running more than one Dendrite on the same Kafka deployment. - TopicPrefix string `yaml:"topic_prefix"` + Addresses []string `json:"Addresses" comment:"List of Kafka addresses to connect to."` + TopicPrefix string `json:"topic_prefix" comment:"The prefix to use for Kafka topic names for this homeserver. Change this only if\nyou are running more than one Dendrite homeserver on the same Kafka deployment."` + UseNaffka bool `json:"UseNaffka" comment:"Whether to use Naffka instead of Kafka. Only available in monolith mode."` + Database DatabaseOptions `json:"NaffkaDatabase" comment:"Naffka database options. Not required when using Kafka."` } func (k *Kafka) TopicFor(name string) string { diff --git a/internal/config/config_keyserver.go b/internal/config/config_keyserver.go index c0967a8ab..ad0f80af5 100644 --- a/internal/config/config_keyserver.go +++ b/internal/config/config_keyserver.go @@ -1,12 +1,11 @@ package config type KeyServer struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - Database DatabaseOptions `yaml:"database"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` } func (c *KeyServer) Defaults() { diff --git a/internal/config/config_mediaapi.go b/internal/config/config_mediaapi.go index 9a4d7e0a2..9170a8408 100644 --- a/internal/config/config_mediaapi.go +++ b/internal/config/config_mediaapi.go @@ -5,34 +5,17 @@ import ( ) type MediaAPI struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // The MediaAPI database stores information about files uploaded and downloaded - // by local users. It is only accessed by the MediaAPI. - Database DatabaseOptions `yaml:"database"` - - // The base path to where the media files will be stored. May be relative or absolute. - BasePath Path `yaml:"base_path"` - - // The absolute base path to where media files will be stored. - AbsBasePath Path `yaml:"-"` - - // The maximum file size in bytes that is allowed to be stored on this server. - // Note: if max_file_size_bytes is set to 0, the size is unlimited. - // Note: if max_file_size_bytes is not set, it will default to 10485760 (10MB) - MaxFileSizeBytes *FileSizeBytes `yaml:"max_file_size_bytes,omitempty"` - - // Whether to dynamically generate thumbnails on-the-fly if the requested resolution is not already generated - DynamicThumbnails bool `yaml:"dynamic_thumbnails"` - - // The maximum number of simultaneous thumbnail generators. default: 10 - MaxThumbnailGenerators int `yaml:"max_thumbnail_generators"` - - // A list of thumbnail sizes to be pre-generated for downloaded remote / uploaded content - ThumbnailSizes []ThumbnailSize `yaml:"thumbnail_sizes"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` + BasePath Path `json:"BasePath" comment:"Storage path for uploaded media. May be relative or absolute."` + AbsBasePath Path `json:"-"` + MaxFileSizeBytes *FileSizeBytes `json:"MaxFileSizeBytes" comment:"The maximum allowed file size (in bytes) for media uploads to this homeserver\n(0 = unlimited)."` + DynamicThumbnails bool `json:"DynamicThumbnails" comment:"Whether to dynamically generate thumbnails if needed."` + MaxThumbnailGenerators int `json:"MaxThumbnailGenerators" comment:"The maximum number of simultaneous thumbnail generators to run."` + ThumbnailSizes []ThumbnailSize `json:"ThumbnailSizes" comment:"A list of thumbnail sizes to be generated for media content."` } func (c *MediaAPI) Defaults() { diff --git a/internal/config/config_roomserver.go b/internal/config/config_roomserver.go index 1a16e2b1f..42f858767 100644 --- a/internal/config/config_roomserver.go +++ b/internal/config/config_roomserver.go @@ -1,12 +1,11 @@ package config type RoomServer struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - Database DatabaseOptions `yaml:"database"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` } func (c *RoomServer) Defaults() { diff --git a/internal/config/config_serverkey.go b/internal/config/config_serverkey.go index cf1f537ab..9ce315502 100644 --- a/internal/config/config_serverkey.go +++ b/internal/config/config_serverkey.go @@ -1,18 +1,14 @@ package config +import "github.com/matrix-org/gomatrixserverlib" + type ServerKeyAPI struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // The ServerKey database caches the public keys of remote servers. - // It may be accessed by the FederationAPI, the ClientAPI, and the MediaAPI. - Database DatabaseOptions `yaml:"database"` - - // Perspective keyservers, to use as a backup when direct key fetch - // requests don't succeed - KeyPerspectives KeyPerspectives `yaml:"key_perspectives"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` + KeyPerspectives KeyPerspectives `json:"PerspectiveServers" comment:"Perspective keyservers to use as a backup when direct key fetches fail."` } func (c *ServerKeyAPI) Defaults() { @@ -27,3 +23,24 @@ func (c *ServerKeyAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { checkNotEmpty(configErrs, "server_key_api.bind", string(c.Bind)) checkNotEmpty(configErrs, "server_key_api.database.connection_string", string(c.Database.ConnectionString)) } + +// KeyPerspectives are used to configure perspective key servers for +// retrieving server keys. +type KeyPerspectives []KeyPerspective + +// KeyPerspectiveTrustKeys denote the signature keys used to trust results. +type KeyPerspectiveTrustKeys struct { + // The key ID, e.g. ed25519:auto + KeyID gomatrixserverlib.KeyID `json:"KeyID"` + // The public key in base64 unpadded format + PublicKey string `json:"PublicKey"` +} + +// KeyPerspective is used to configure a key perspective server. +type KeyPerspective struct { + // The server name of the perspective key server + ServerName gomatrixserverlib.ServerName `json:"ServerName"` + // Server keys for the perspective user, used to verify the + // keys have been signed by the perspective server + Keys []KeyPerspectiveTrustKeys `json:"TrustKeys"` +} diff --git a/internal/config/config_syncapi.go b/internal/config/config_syncapi.go index 488f6658d..a2d06aabd 100644 --- a/internal/config/config_syncapi.go +++ b/internal/config/config_syncapi.go @@ -1,12 +1,11 @@ package config type SyncAPI struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - Database DatabaseOptions `yaml:"database"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + Database DatabaseOptions `json:"Database" comment:"Database configuration for this component."` } func (c *SyncAPI) Defaults() { diff --git a/internal/config/config_userapi.go b/internal/config/config_userapi.go index f7da9e593..f01eaf97b 100644 --- a/internal/config/config_userapi.go +++ b/internal/config/config_userapi.go @@ -1,17 +1,12 @@ package config type UserAPI struct { - Matrix *Global `yaml:"-"` + Matrix *Global `json:"-"` - Listen Address `yaml:"listen"` - Bind Address `yaml:"bind"` - - // The Account database stores the login details and account information - // for local users. It is accessed by the UserAPI. - AccountDatabase DatabaseOptions `yaml:"account_database"` - // The Device database stores session information for the devices of logged - // in local users. It is accessed by the UserAPI. - DeviceDatabase DatabaseOptions `yaml:"device_database"` + Listen Address `json:"Listen" comment:"Listen address for this component."` + Bind Address `json:"Bind" comment:"Bind address for this component."` + AccountDatabase DatabaseOptions `json:"AccountDatabase" comment:"Database configuration for the account database."` + DeviceDatabase DatabaseOptions `json:"DeviceDatabase" comment:"Database configuration for the device database."` } func (c *UserAPI) Defaults() { diff --git a/internal/httputil/httpapi.go b/internal/httputil/httpapi.go index 8f7723efa..3f63b7a55 100644 --- a/internal/httputil/httpapi.go +++ b/internal/httputil/httpapi.go @@ -40,12 +40,6 @@ import ( "github.com/sirupsen/logrus" ) -// BasicAuth is used for authorization on /metrics handlers -type BasicAuth struct { - Username string `yaml:"username"` - Password string `yaml:"password"` -} - // MakeAuthAPI turns a util.JSONRequestHandler function into an http.Handler which authenticates the request. func MakeAuthAPI( metricsName string, userAPI userapi.UserInternalAPI, @@ -245,7 +239,7 @@ func SetupHTTPAPI(servMux, publicApiMux, internalApiMux *mux.Router, cfg *config } // WrapHandlerInBasicAuth adds basic auth to a handler. Only used for /metrics -func WrapHandlerInBasicAuth(h http.Handler, b BasicAuth) http.HandlerFunc { +func WrapHandlerInBasicAuth(h http.Handler, b config.BasicAuth) http.HandlerFunc { if b.Username == "" || b.Password == "" { logrus.Warn("Metrics are exposed without protection. Make sure you set up protection at proxy level.") } diff --git a/internal/httputil/httpapi_test.go b/internal/httputil/httpapi_test.go index de6ccf9b4..be6fe9bba 100644 --- a/internal/httputil/httpapi_test.go +++ b/internal/httputil/httpapi_test.go @@ -18,12 +18,14 @@ import ( "net/http" "net/http/httptest" "testing" + + "github.com/matrix-org/dendrite/internal/config" ) func TestWrapHandlerInBasicAuth(t *testing.T) { type args struct { h http.Handler - b BasicAuth + b config.BasicAuth } dummyHandler := http.HandlerFunc(func(h http.ResponseWriter, r *http.Request) { @@ -46,7 +48,7 @@ func TestWrapHandlerInBasicAuth(t *testing.T) { name: "only user set", args: args{ h: dummyHandler, - b: BasicAuth{Username: "test"}, // no basic auth + b: config.BasicAuth{Username: "test"}, // no basic auth }, want: http.StatusOK, reqAuth: false, @@ -55,7 +57,7 @@ func TestWrapHandlerInBasicAuth(t *testing.T) { name: "only pass set", args: args{ h: dummyHandler, - b: BasicAuth{Password: "test"}, // no basic auth + b: config.BasicAuth{Password: "test"}, // no basic auth }, want: http.StatusOK, reqAuth: false, @@ -64,7 +66,7 @@ func TestWrapHandlerInBasicAuth(t *testing.T) { name: "credentials correct", args: args{ h: dummyHandler, - b: BasicAuth{Username: "test", Password: "test"}, // basic auth enabled + b: config.BasicAuth{Username: "test", Password: "test"}, // basic auth enabled }, want: http.StatusOK, reqAuth: true, @@ -73,7 +75,7 @@ func TestWrapHandlerInBasicAuth(t *testing.T) { name: "credentials wrong", args: args{ h: dummyHandler, - b: BasicAuth{Username: "test1", Password: "test"}, // basic auth enabled + b: config.BasicAuth{Username: "test1", Password: "test"}, // basic auth enabled }, want: http.StatusForbidden, reqAuth: true, @@ -82,7 +84,7 @@ func TestWrapHandlerInBasicAuth(t *testing.T) { name: "no basic auth in request", args: args{ h: dummyHandler, - b: BasicAuth{Username: "test", Password: "test"}, // basic auth enabled + b: config.BasicAuth{Username: "test", Password: "test"}, // basic auth enabled }, want: http.StatusForbidden, reqAuth: false,