Skip to content

Commit d1f64ac

Browse files
committed
Adapted implementation based on new design in prometheus/common
Signed-off-by: Marco Pracucci <[email protected]>
1 parent 127ac66 commit d1f64ac

File tree

5 files changed

+39
-74
lines changed

5 files changed

+39
-74
lines changed

pkg/alertmanager/alertmanager.go

+23-13
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ import (
4040
"github.com/prometheus/alertmanager/ui"
4141
"github.com/prometheus/client_golang/prometheus"
4242
"github.com/prometheus/client_golang/prometheus/promauto"
43+
commoncfg "github.com/prometheus/common/config"
4344
"github.com/prometheus/common/model"
4445
"github.com/prometheus/common/route"
4546

4647
"github.com/cortexproject/cortex/pkg/alertmanager/alertstore"
48+
util_net "github.com/cortexproject/cortex/pkg/util/net"
4749
"github.com/cortexproject/cortex/pkg/util/services"
4850
)
4951

@@ -95,6 +97,7 @@ type Alertmanager struct {
9597
wg sync.WaitGroup
9698
mux *http.ServeMux
9799
registry *prometheus.Registry
100+
firewallDialer *util_net.FirewallDialer
98101

99102
// The Dispatcher is the only component we need to recreate when we call ApplyConfig.
100103
// Given its metrics don't have any variable labels we need to re-use the same metrics.
@@ -148,6 +151,10 @@ func New(cfg *Config, reg *prometheus.Registry) (*Alertmanager, error) {
148151
cfg: cfg,
149152
logger: log.With(cfg.Logger, "user", cfg.UserID),
150153
stop: make(chan struct{}),
154+
firewallDialer: util_net.NewFirewallDialer(util_net.FirewallDialerConfig{
155+
BlockCIDRNetworks: cfg.ReceiversFirewall.Block.CIDRNetworks,
156+
BlockPrivateAddresses: cfg.ReceiversFirewall.Block.PrivateAddresses,
157+
}),
151158
configHashMetric: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
152159
Name: "alertmanager_config_hash",
153160
Help: "Hash of the currently loaded alertmanager configuration.",
@@ -280,8 +287,6 @@ func clusterWait(position func() int, timeout time.Duration) func() time.Duratio
280287

281288
// ApplyConfig applies a new configuration to an Alertmanager.
282289
func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config, rawCfg string) error {
283-
conf = injectFirewallToAlertmanagerConfig(conf, am.cfg.ReceiversFirewall)
284-
285290
templateFiles := make([]string, len(conf.Templates))
286291
if len(conf.Templates) > 0 {
287292
for i, t := range conf.Templates {
@@ -318,7 +323,7 @@ func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config, rawCfg s
318323
return d + waitFunc()
319324
}
320325

321-
integrationsMap, err := buildIntegrationsMap(conf.Receivers, tmpl, am.logger)
326+
integrationsMap, err := buildIntegrationsMap(conf.Receivers, tmpl, am.firewallDialer, am.logger)
322327
if err != nil {
323328
return nil
324329
}
@@ -410,10 +415,10 @@ func (am *Alertmanager) getFullState() (*clusterpb.FullState, error) {
410415

411416
// buildIntegrationsMap builds a map of name to the list of integration notifiers off of a
412417
// list of receiver config.
413-
func buildIntegrationsMap(nc []*config.Receiver, tmpl *template.Template, logger log.Logger) (map[string][]notify.Integration, error) {
418+
func buildIntegrationsMap(nc []*config.Receiver, tmpl *template.Template, firewallDialer *util_net.FirewallDialer, logger log.Logger) (map[string][]notify.Integration, error) {
414419
integrationsMap := make(map[string][]notify.Integration, len(nc))
415420
for _, rcv := range nc {
416-
integrations, err := buildReceiverIntegrations(rcv, tmpl, logger)
421+
integrations, err := buildReceiverIntegrations(rcv, tmpl, firewallDialer, logger)
417422
if err != nil {
418423
return nil, err
419424
}
@@ -425,7 +430,7 @@ func buildIntegrationsMap(nc []*config.Receiver, tmpl *template.Template, logger
425430
// buildReceiverIntegrations builds a list of integration notifiers off of a
426431
// receiver config.
427432
// Taken from https://github.com/prometheus/alertmanager/blob/94d875f1227b29abece661db1a68c001122d1da5/cmd/alertmanager/main.go#L112-L159.
428-
func buildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template, logger log.Logger) ([]notify.Integration, error) {
433+
func buildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template, firewallDialer *util_net.FirewallDialer, logger log.Logger) ([]notify.Integration, error) {
429434
var (
430435
errs types.MultiError
431436
integrations []notify.Integration
@@ -439,29 +444,34 @@ func buildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template, log
439444
}
440445
)
441446

447+
// Inject the firewall to any receiver integration supporting it.
448+
httpOps := []commoncfg.HTTPClientOption{
449+
commoncfg.WithDialContextFunc(firewallDialer.DialContext),
450+
}
451+
442452
for i, c := range nc.WebhookConfigs {
443-
add("webhook", i, c, func(l log.Logger) (notify.Notifier, error) { return webhook.New(c, tmpl, l) })
453+
add("webhook", i, c, func(l log.Logger) (notify.Notifier, error) { return webhook.New(c, tmpl, l, httpOps...) })
444454
}
445455
for i, c := range nc.EmailConfigs {
446456
add("email", i, c, func(l log.Logger) (notify.Notifier, error) { return email.New(c, tmpl, l), nil })
447457
}
448458
for i, c := range nc.PagerdutyConfigs {
449-
add("pagerduty", i, c, func(l log.Logger) (notify.Notifier, error) { return pagerduty.New(c, tmpl, l) })
459+
add("pagerduty", i, c, func(l log.Logger) (notify.Notifier, error) { return pagerduty.New(c, tmpl, l, httpOps...) })
450460
}
451461
for i, c := range nc.OpsGenieConfigs {
452-
add("opsgenie", i, c, func(l log.Logger) (notify.Notifier, error) { return opsgenie.New(c, tmpl, l) })
462+
add("opsgenie", i, c, func(l log.Logger) (notify.Notifier, error) { return opsgenie.New(c, tmpl, l, httpOps...) })
453463
}
454464
for i, c := range nc.WechatConfigs {
455-
add("wechat", i, c, func(l log.Logger) (notify.Notifier, error) { return wechat.New(c, tmpl, l) })
465+
add("wechat", i, c, func(l log.Logger) (notify.Notifier, error) { return wechat.New(c, tmpl, l, httpOps...) })
456466
}
457467
for i, c := range nc.SlackConfigs {
458-
add("slack", i, c, func(l log.Logger) (notify.Notifier, error) { return slack.New(c, tmpl, l) })
468+
add("slack", i, c, func(l log.Logger) (notify.Notifier, error) { return slack.New(c, tmpl, l, httpOps...) })
459469
}
460470
for i, c := range nc.VictorOpsConfigs {
461-
add("victorops", i, c, func(l log.Logger) (notify.Notifier, error) { return victorops.New(c, tmpl, l) })
471+
add("victorops", i, c, func(l log.Logger) (notify.Notifier, error) { return victorops.New(c, tmpl, l, httpOps...) })
462472
}
463473
for i, c := range nc.PushoverConfigs {
464-
add("pushover", i, c, func(l log.Logger) (notify.Notifier, error) { return pushover.New(c, tmpl, l) })
474+
add("pushover", i, c, func(l log.Logger) (notify.Notifier, error) { return pushover.New(c, tmpl, l, httpOps...) })
465475
}
466476
if errs.Len() > 0 {
467477
return nil, &errs

pkg/alertmanager/firewall.go

+4-54
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import (
44
"flag"
55
"fmt"
66

7-
"github.com/prometheus/alertmanager/config"
8-
commoncfg "github.com/prometheus/common/config"
9-
107
"github.com/cortexproject/cortex/pkg/util/flagext"
11-
netutil "github.com/cortexproject/cortex/pkg/util/net"
128
)
139

1410
type FirewallConfig struct {
@@ -20,57 +16,11 @@ func (cfg *FirewallConfig) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSe
2016
}
2117

2218
type FirewallHostsSpec struct {
23-
CIDRs flagext.CIDRSliceCSV `yaml:"cidrs"`
24-
Private bool `yaml:"private_addresses"`
19+
CIDRNetworks flagext.CIDRSliceCSV `yaml:"cidr_networks"`
20+
PrivateAddresses bool `yaml:"private_addresses"`
2521
}
2622

2723
func (cfg *FirewallHostsSpec) RegisterFlagsWithPrefix(prefix, action string, f *flag.FlagSet) {
28-
f.Var(&cfg.CIDRs, prefix+".cidrs", fmt.Sprintf("Comma-separated list of network CIDRs to %s in Alertmanager receiver integrations.", action))
29-
f.BoolVar(&cfg.Private, prefix+".private-addresses", false, fmt.Sprintf("True to %s private and local addresses in Alertmanager receiver integrations.", action))
30-
}
31-
32-
func injectFirewallToAlertmanagerConfig(conf *config.Config, firewallCfg FirewallConfig) *config.Config {
33-
firewall := netutil.NewFirewallDialer(netutil.FirewallDialerConfig{
34-
BlockCIDRs: firewallCfg.Block.CIDRs,
35-
BlockPrivate: firewallCfg.Block.Private,
36-
})
37-
38-
conf.Global.HTTPConfig = injectFirewallToHTTPConfig(conf.Global.HTTPConfig, firewall)
39-
40-
for _, receiver := range conf.Receivers {
41-
for _, rc := range receiver.WebhookConfigs {
42-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
43-
}
44-
for _, rc := range receiver.SlackConfigs {
45-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
46-
}
47-
for _, rc := range receiver.PushoverConfigs {
48-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
49-
}
50-
for _, rc := range receiver.PagerdutyConfigs {
51-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
52-
}
53-
for _, rc := range receiver.OpsGenieConfigs {
54-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
55-
}
56-
for _, rc := range receiver.WechatConfigs {
57-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
58-
}
59-
for _, rc := range receiver.VictorOpsConfigs {
60-
rc.HTTPConfig = injectFirewallToHTTPConfig(rc.HTTPConfig, firewall)
61-
}
62-
}
63-
64-
return conf
65-
}
66-
67-
func injectFirewallToHTTPConfig(conf *commoncfg.HTTPClientConfig, firewall *netutil.FirewallDialer) *commoncfg.HTTPClientConfig {
68-
if conf == nil {
69-
return &commoncfg.HTTPClientConfig{
70-
DialContext: firewall.DialContext,
71-
}
72-
}
73-
74-
conf.DialContext = firewall.DialContext
75-
return conf
24+
f.Var(&cfg.CIDRNetworks, prefix+".cidr_networks", fmt.Sprintf("Comma-separated list of network CIDRs to %s in Alertmanager receiver integrations.", action))
25+
f.BoolVar(&cfg.PrivateAddresses, prefix+".private-addresses", false, fmt.Sprintf("True to %s private and local addresses in Alertmanager receiver integrations.", action))
7626
}

pkg/alertmanager/multitenant_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ receivers:
386386

387387
// Prepare the alertmanager config.
388388
cfg := mockAlertmanagerConfig(t)
389-
cfg.ReceiversFirewall.Block.Private = firewallEnabled
389+
cfg.ReceiversFirewall.Block.PrivateAddresses = firewallEnabled
390390

391391
// Start the alertmanager.
392392
reg := prometheus.NewPedanticRegistry()

pkg/util/net/firewall_dialer.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ var errBlockedAddress = errors.New("blocked address")
1414
var errInvalidAddress = errors.New("invalid address")
1515

1616
type FirewallDialerConfig struct {
17-
BlockCIDRs []flagext.CIDR
18-
BlockPrivate bool
17+
BlockCIDRNetworks []flagext.CIDR
18+
BlockPrivateAddresses bool
1919
}
2020

2121
// FirewallDialer is a net dialer which integrates a firewall to block specific addresses.
@@ -35,6 +35,11 @@ func (d *FirewallDialer) DialContext(ctx context.Context, network, address strin
3535
}
3636

3737
func (d *FirewallDialer) control(_, address string, _ syscall.RawConn) error {
38+
// Skip any control if no firewall has been configured.
39+
if !d.cfg.BlockPrivateAddresses && len(d.cfg.BlockCIDRNetworks) == 0 {
40+
return nil
41+
}
42+
3843
host, _, err := net.SplitHostPort(address)
3944
if err != nil {
4045
return errInvalidAddress
@@ -46,11 +51,11 @@ func (d *FirewallDialer) control(_, address string, _ syscall.RawConn) error {
4651
return errBlockedAddress
4752
}
4853

49-
if d.cfg.BlockPrivate && (isPrivate(ip) || isLocal(ip)) {
54+
if d.cfg.BlockPrivateAddresses && (isPrivate(ip) || isLocal(ip)) {
5055
return errBlockedAddress
5156
}
5257

53-
for _, cidr := range d.cfg.BlockCIDRs {
58+
for _, cidr := range d.cfg.BlockCIDRNetworks {
5459
if cidr.Value.Contains(ip) {
5560
return errBlockedAddress
5661
}

pkg/util/net/firewall_dialer_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func TestFirewallDialer(t *testing.T) {
3838
},
3939
"should support blocking private addresses": {
4040
cfg: FirewallDialerConfig{
41-
BlockPrivate: true,
41+
BlockPrivateAddresses: true,
4242
},
4343
cases: []testCase{
4444
{"localhost", true},
@@ -56,7 +56,7 @@ func TestFirewallDialer(t *testing.T) {
5656
},
5757
"should support blocking custom CIDRs": {
5858
cfg: FirewallDialerConfig{
59-
BlockCIDRs: []flagext.CIDR{blockedCIDR},
59+
BlockCIDRNetworks: []flagext.CIDR{blockedCIDR},
6060
},
6161
cases: []testCase{
6262
{"localhost", false},

0 commit comments

Comments
 (0)