-
Notifications
You must be signed in to change notification settings - Fork 1
/
global.go
165 lines (142 loc) · 5.37 KB
/
global.go
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
package config
import (
"crypto/x509"
"errors"
"time"
"github.com/getlantern/fronted"
"github.com/getlantern/keyman"
"github.com/getlantern/flashlight/v7/browsers/simbrowser"
"github.com/getlantern/flashlight/v7/domainrouting"
"github.com/getlantern/flashlight/v7/embeddedconfig"
"github.com/getlantern/flashlight/v7/otel"
)
// Global contains general configuration for Lantern either set globally via
// the cloud, in command line flags, or in local customizations during
// development.
type Global struct {
Version int
CloudConfigCA string
// AutoUpdateCA is the CA key to pin for auto-updates.
AutoUpdateCA string
UpdateServerURL string
BordaReportInterval time.Duration
BordaSamplePercentage float64
// ReportIssueEmail is the recipient of the email sent when the user
// reports issue.
ReportIssueEmail string
// AdSettings are the settings to use for showing ads to mobile clients
AdSettings *AdSettings
Client *ClientConfig
// ProxiedSites are domains that get routed through Lantern rather than accessed directly.
// This has been deprecated in favor of more precise DomainRoutingRules (see below).
// The client will continue to honor ProxiedSites configuration for now.
ProxiedSites *domainrouting.ProxiedSitesConfig
// DomainRoutingRules specifies routing rules for specific domains, such as forcing proxing, forcing direct dials, etc.
DomainRoutingRules domainrouting.RulesMap
// NamedDomainRoutingRules specifies routing rules for specific domains, grouped by name.
NamedDomainRoutingRules map[string]domainrouting.RulesMap
// TrustedCAs are trusted CAs for domain fronting domains only.
TrustedCAs []*fronted.CA
// GlobalConfigPollInterval sets interval at which to poll for global config
GlobalConfigPollInterval time.Duration
// ProxyConfigPollInterval sets interval at which to poll for proxy config
ProxyConfigPollInterval time.Duration
// FeaturesEnabled specifies which optional feature is enabled for certain
// groups of clients.
FeaturesEnabled map[string][]*ClientGroup
// FeatureOptions is a generic way to specify options for optional
// features. It's up to the feature code to handle the raw JSON message.
FeatureOptions map[string]map[string]interface{}
// Market share data used by the simbrowser package when picking a browser to simulate.
GlobalBrowserMarketShareData simbrowser.MarketShareData
RegionalBrowserMarketShareData map[simbrowser.CountryCode]simbrowser.MarketShareData
// Configuration for OpenTelemetry
Otel *otel.Config
}
// NewGlobal creates a new global config with otherwise nil values set.
func NewGlobal() *Global {
return &Global{
Client: NewClientConfig(),
ProxiedSites: &domainrouting.ProxiedSitesConfig{},
}
}
// FeatureEnabled checks if the feature is enabled given the client properties.
func (cfg *Global) FeatureEnabled(feature, platform, appName, version string, userID int64, isPro bool,
geoCountry string) bool {
enabled, _ := cfg.FeatureEnabledWithLabel(feature, platform, appName, version, userID, isPro, geoCountry)
log.Tracef("Feature %v enabled for user %v in country %v?: %v", feature, userID, geoCountry, enabled)
return enabled
}
// FeatureEnabledWithLabel is the same as FeatureEnabled but also returns the
// label of the first matched ClientGroup if the feature is enabled.
func (cfg *Global) FeatureEnabledWithLabel(feature, platform, appName, version string, userID int64, isPro bool,
geoCountry string) (enabled bool, label string) {
groups, exists := cfg.FeaturesEnabled[feature]
if !exists {
return false, ""
}
for _, g := range groups {
if g.Includes(platform, appName, version, userID, isPro, geoCountry) {
return true, g.Label
}
}
return false, ""
}
func (cfg *Global) UnmarshalFeatureOptions(feature string, opts FeatureOptions) error {
m, exists := cfg.FeatureOptions[feature]
if !exists {
return errAbsentOption
}
return opts.FromMap(m)
}
// TrustedCACerts returns a certificate pool containing the TrustedCAs from this
// config.
func (cfg *Global) TrustedCACerts() (pool *x509.CertPool, err error) {
certs := make([]string, 0, len(cfg.TrustedCAs))
for _, ca := range cfg.TrustedCAs {
certs = append(certs, ca.Cert)
}
pool, err = keyman.PoolContainingCerts(certs...)
if err != nil {
log.Errorf("Could not create pool %v", err)
}
return
}
// applyFlags updates this config from any command-line flags that were passed
// in.
func (cfg *Global) applyFlags(flags map[string]interface{}) {
// Visit all flags that have been set and copy to config
for key, value := range flags {
switch key {
case "cloudconfigca":
cfg.CloudConfigCA = value.(string)
case "borda-report-interval":
cfg.BordaReportInterval = value.(time.Duration)
case "borda-sample-percentage":
cfg.BordaSamplePercentage = value.(float64)
}
}
}
func (cfg *Global) validate() error {
err := cfg.Client.Validate()
if err != nil {
return err
}
if len(cfg.TrustedCAs) == 0 {
return errors.New("no trusted CAs")
}
for _, groups := range cfg.FeaturesEnabled {
for _, g := range groups {
if err := g.Validate(); err != nil {
return err
}
}
}
return nil
}
// Returns the global config in structured form, by executing the template without any data. This is useful for consuming parts of the config that aren't templatized.
func GetEmbeddedGlobalSansTemplateData() (*Global, error) {
var g Global
err := embeddedconfig.ExecuteAndUnmarshalGlobal(nil, &g)
return &g, err
}