mirror of
https://github.com/pomerium/pomerium.git
synced 2025-08-06 10:21:05 +02:00
support host:port in metrics_address (#2042)
This commit is contained in:
parent
4218f49741
commit
c27cd9030d
6 changed files with 91 additions and 25 deletions
|
@ -690,7 +690,7 @@ func (o *Options) Validate() error {
|
|||
}
|
||||
|
||||
if o.MetricsAddr != "" {
|
||||
if err := ValidateListenerAddress(o.MetricsAddr); err != nil {
|
||||
if err := ValidateMetricsAddress(o.MetricsAddr); err != nil {
|
||||
return fmt.Errorf("config: invalid metrics_addr: %w", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package config
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||
|
@ -39,15 +40,19 @@ func GetEnvoyDNSLookupFamily(value string) envoy_config_cluster_v3.Cluster_DnsLo
|
|||
return envoy_config_cluster_v3.Cluster_AUTO
|
||||
}
|
||||
|
||||
// ValidateListenerAddress validates that a listener address is ip:port, not host:port.
|
||||
func ValidateListenerAddress(addr string) error {
|
||||
host, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid address, expected host:port")
|
||||
// ValidateMetricsAddress validates address for the metrics
|
||||
func ValidateMetricsAddress(addr string) error {
|
||||
_, port, err := net.SplitHostPort(addr)
|
||||
if err != nil || port == "" {
|
||||
return fmt.Errorf("expected host:port")
|
||||
}
|
||||
|
||||
if host != "" && net.ParseIP(host) == nil {
|
||||
return fmt.Errorf("invalid address, expected ip for host")
|
||||
p, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return fmt.Errorf("port must be a number")
|
||||
}
|
||||
if p <= 0 {
|
||||
return fmt.Errorf("expected positive port number")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -224,9 +224,22 @@ func (srv *Server) buildMetricsListener(cfg *config.Config) (*envoy_config_liste
|
|||
}
|
||||
}
|
||||
|
||||
// we ignore the host part of the address, only binding to
|
||||
host, port, err := net.SplitHostPort(cfg.Options.MetricsAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("metrics_addr %s: %w", cfg.Options.MetricsAddr, err)
|
||||
}
|
||||
if port == "" {
|
||||
return nil, fmt.Errorf("metrics_addr %s: port is required", cfg.Options.MetricsAddr)
|
||||
}
|
||||
// unless an explicit IP address was provided, and bind to all interfaces if hostname was provided
|
||||
if net.ParseIP(host) == nil {
|
||||
host = ""
|
||||
}
|
||||
|
||||
li := &envoy_config_listener_v3.Listener{
|
||||
Name: "metrics-ingress",
|
||||
Address: buildAddress(cfg.Options.MetricsAddr, 9902),
|
||||
Address: buildAddress(fmt.Sprintf("%s:%s", host, port), 9902),
|
||||
FilterChains: []*envoy_config_listener_v3.FilterChain{filterChain},
|
||||
}
|
||||
return li, nil
|
||||
|
|
|
@ -19,4 +19,5 @@ const (
|
|||
var (
|
||||
errNoMetricsAddr = errors.New("no metrics address provided")
|
||||
errNoMetricsPort = errors.New("no metrics port provided")
|
||||
errNoMetricsHost = errors.New("no metrics host provided")
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
|
@ -30,7 +30,7 @@ func (r *Reporter) OnConfigChange(cfg *config.Config) {
|
|||
|
||||
services, err := getReportedServices(cfg)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("applying config")
|
||||
log.Error().Err(err).Msg("service registry reporter")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ func (r *Reporter) OnConfigChange(cfg *config.Config) {
|
|||
}
|
||||
|
||||
func getReportedServices(cfg *config.Config) ([]*pb.Service, error) {
|
||||
mu, err := metricsURL(cfg.Options.MetricsAddr)
|
||||
mu, err := metricsURL(*cfg.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -79,12 +79,34 @@ func getReportedServices(cfg *config.Config) ([]*pb.Service, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func metricsURL(addr string) (*url.URL, error) {
|
||||
if addr == "" {
|
||||
func metricsURL(o config.Options) (*url.URL, error) {
|
||||
u := url.URL{
|
||||
Scheme: "http",
|
||||
Host: o.MetricsAddr,
|
||||
Path: defaultMetricsPath,
|
||||
}
|
||||
|
||||
if o.MetricsBasicAuth != "" {
|
||||
txt, err := base64.StdEncoding.DecodeString(o.MetricsBasicAuth)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("metrics basic auth: %w", err)
|
||||
}
|
||||
parts := strings.SplitN(string(txt), ":", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("expected username:password for basic auth")
|
||||
}
|
||||
u.User = url.UserPassword(parts[0], parts[1])
|
||||
}
|
||||
|
||||
if o.MetricsCertificate != "" || o.MetricsCertificateFile != "" {
|
||||
u.Scheme = "https"
|
||||
}
|
||||
|
||||
if o.MetricsAddr == "" {
|
||||
return nil, errNoMetricsAddr
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
host, port, err := net.SplitHostPort(o.MetricsAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid metrics address: %w", err)
|
||||
}
|
||||
|
@ -94,18 +116,10 @@ func metricsURL(addr string) (*url.URL, error) {
|
|||
}
|
||||
|
||||
if host == "" {
|
||||
host, err = os.Hostname()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("metrics address is missing hostname, error obtaining it from OS: %w", err)
|
||||
}
|
||||
return nil, errNoMetricsHost
|
||||
}
|
||||
|
||||
return &url.URL{
|
||||
// TODO: TLS selector https://github.com/pomerium/internal/issues/272
|
||||
Scheme: "http",
|
||||
Path: defaultMetricsPath,
|
||||
Host: net.JoinHostPort(host, port),
|
||||
}, nil
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func runReporter(
|
||||
|
|
33
internal/registry/reporter_test.go
Normal file
33
internal/registry/reporter_test.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pomerium/pomerium/config"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMetricsURL(t *testing.T) {
|
||||
for opt, expect := range map[*config.Options]string{
|
||||
{MetricsAddr: "my.host:9090"}: "http://my.host:9090/metrics",
|
||||
{MetricsAddr: "my.host:9090", MetricsBasicAuth: "bXl1c2VyOm15cGFzc3dvcmQ="}: "http://myuser:mypassword@my.host:9090/metrics",
|
||||
{MetricsAddr: "my.host:9090", MetricsCertificate: "CERT"}: "https://my.host:9090/metrics",
|
||||
{MetricsAddr: "my.host:9090", MetricsCertificateFile: "CERT"}: "https://my.host:9090/metrics",
|
||||
} {
|
||||
u, err := metricsURL(*opt)
|
||||
if assert.NoError(t, err, opt) {
|
||||
assert.Equal(t, expect, u.String())
|
||||
}
|
||||
}
|
||||
|
||||
for _, opt := range []config.Options{
|
||||
{MetricsAddr: "my.host:"},
|
||||
{MetricsAddr: "my.host:9090", MetricsBasicAuth: "SMTH"},
|
||||
{MetricsAddr: ":9090"},
|
||||
{MetricsAddr: "my.host"},
|
||||
} {
|
||||
_, err := metricsURL(opt)
|
||||
assert.Error(t, err, opt)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue