Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add TLS to Metrics and Telemetry servers #7041

Merged
merged 11 commits into from
Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions cmd/argo/commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth"
restclient "k8s.io/client-go/rest"
"k8s.io/utils/env"

"github.com/argoproj/argo-workflows/v3"
"github.com/argoproj/argo-workflows/v3/cmd/argo/commands/client"
Expand Down Expand Up @@ -105,20 +104,10 @@ See %s`, help.ArgoServer),
var tlsConfig *tls.Config
if secure {
log.Infof("Generating Self Signed TLS Certificates for Secure Mode")
tlsMinVersion, err := env.GetInt("TLS_MIN_VERSION", tls.VersionTLS12)
tlsConfig, err = tlsutils.GenerateTLSConfig()
if err != nil {
return err
}
var cer *tls.Certificate
cer, err = tlsutils.GenerateX509KeyPair()
if err != nil {
return err
}
tlsConfig = &tls.Config{
Certificates: []tls.Certificate{*cer},
MinVersion: uint16(tlsMinVersion),
InsecureSkipVerify: true,
}
} else {
log.Warn("You are running in insecure mode. Learn how to enable transport layer security: https://argoproj.github.io/argo-workflows/tls/")
}
Expand Down
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ type MetricsConfig struct {
Port int `json:"port,omitempty"`
// IgnoreErrors is a flag that instructs prometheus to ignore metric emission errors
IgnoreErrors bool `json:"ignoreErrors,omitempty"`
// Secure is a flag that starts the metrics servers using TLS
Secure *bool `json:secure,omitempty`
simster7 marked this conversation as resolved.
Show resolved Hide resolved
}

type WorkflowRestrictions struct {
Expand Down
3 changes: 3 additions & 0 deletions docs/workflow-controller-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ data:
metricsTTL: "10m"
# IgnoreErrors is a flag that instructs prometheus to ignore metric emission errors. Default is "false"
ignoreErrors: false
# Use a self-signed cert for TLS, default false
secure: false

# DEPRECATED: Legacy metrics are now removed, this field is ignored
disableLegacy: false
Expand All @@ -234,6 +236,7 @@ data:
enabled: true
path: /telemetry
port: 8080
secure: true # Use a self-signed cert for TLS, default false

# enable persistence using postgres
persistence: |
Expand Down
19 changes: 19 additions & 0 deletions util/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"net"
"os"
"time"

"k8s.io/utils/env"
)

func pemBlockForKey(priv interface{}) *pem.Block {
Expand Down Expand Up @@ -100,3 +102,20 @@ func GenerateX509KeyPair() (*tls.Certificate, error) {
}
return &cert, nil
}

func GenerateTLSConfig() (*tls.Config, error) {
tlsMinVersion, err := env.GetInt("TLS_MIN_VERSION", tls.VersionTLS12)
if err != nil {
return nil, err
}
var cer *tls.Certificate
cer, err = GenerateX509KeyPair()
if err != nil {
return nil, err
}
return &tls.Config{
Certificates: []tls.Certificate{*cer},
MinVersion: uint16(tlsMinVersion),
InsecureSkipVerify: true,
}, nil
}
12 changes: 12 additions & 0 deletions workflow/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1122,12 +1122,17 @@ func (wfc *WorkflowController) getMetricsServerConfig() (metrics.ServerConfig, m
if port == 0 {
port = metrics.DefaultMetricsServerPort
}
secure := false
if wfc.Config.MetricsConfig.Secure != nil {
simster7 marked this conversation as resolved.
Show resolved Hide resolved
secure = *wfc.Config.MetricsConfig.Secure
}
metricsConfig := metrics.ServerConfig{
Enabled: wfc.Config.MetricsConfig.Enabled == nil || *wfc.Config.MetricsConfig.Enabled,
Path: path,
Port: port,
TTL: time.Duration(wfc.Config.MetricsConfig.MetricsTTL),
IgnoreErrors: wfc.Config.MetricsConfig.IgnoreErrors,
Secure: secure,
}

// Telemetry config
Expand All @@ -1140,11 +1145,18 @@ func (wfc *WorkflowController) getMetricsServerConfig() (metrics.ServerConfig, m
if wfc.Config.TelemetryConfig.Port > 0 {
port = wfc.Config.TelemetryConfig.Port
}

secure = metricsConfig.Secure
if wfc.Config.TelemetryConfig.Secure != nil {
simster7 marked this conversation as resolved.
Show resolved Hide resolved
secure = *wfc.Config.TelemetryConfig.Secure
}

telemetryConfig := metrics.ServerConfig{
Enabled: wfc.Config.TelemetryConfig.Enabled == nil || *wfc.Config.TelemetryConfig.Enabled,
Path: path,
Port: port,
IgnoreErrors: wfc.Config.TelemetryConfig.IgnoreErrors,
Secure: secure,
}
return metricsConfig, telemetryConfig
}
Expand Down
3 changes: 2 additions & 1 deletion workflow/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ type ServerConfig struct {
Port int
TTL time.Duration
IgnoreErrors bool
Secure bool
}

func (s ServerConfig) SameServerAs(other ServerConfig) bool {
return s.Port == other.Port && s.Path == other.Path && s.Enabled && other.Enabled
return s.Port == other.Port && s.Path == other.Path && s.Enabled && other.Enabled && s.Secure == other.Secure
simster7 marked this conversation as resolved.
Show resolved Hide resolved
}

type metric struct {
Expand Down
25 changes: 21 additions & 4 deletions workflow/metrics/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
runtimeutil "k8s.io/apimachinery/pkg/util/runtime"

tlsutils "github.com/argoproj/argo-workflows/v3/util/tls"
)

// RunServer starts a metrics server
Expand Down Expand Up @@ -51,12 +53,27 @@ func runServer(config ServerConfig, registry *prometheus.Registry, ctx context.C
mux.Handle(config.Path, promhttp.HandlerFor(registry, handlerOpts))
srv := &http.Server{Addr: fmt.Sprintf(":%v", config.Port), Handler: mux}

go func() {
log.Infof("Starting prometheus metrics server at localhost:%v%s", config.Port, config.Path)
if err := srv.ListenAndServe(); err != nil {
if config.Secure {
log.Infof("Generating Self Signed TLS Certificates for Telemetry Servers")
tlsConfig, err := tlsutils.GenerateTLSConfig()
if err != nil {
panic(err)
}
}()
srv.TLSConfig = tlsConfig
go func() {
log.Infof("Starting prometheus metrics server at localhost:%v%s", config.Port, config.Path)
if err := srv.ListenAndServeTLS("", ""); err != nil {
panic(err)
}
}()
} else {
go func() {
log.Infof("Starting prometheus metrics server at localhost:%v%s", config.Port, config.Path)
if err := srv.ListenAndServe(); err != nil {
panic(err)
}
}()
}

// Waiting for stop signal
<-ctx.Done()
Expand Down