Skip to content

Commit

Permalink
api/vmalertmanager: adds webserver configuration (#1045)
Browse files Browse the repository at this point in the history
* api/vmalertmanager: adds webserver configuration

Adds a new type for generic webserver TLS configuration.

* First of all, it allows to properly configure alertmanager and detect tls related params for it.
 It fixes scheme detection for probes, AsURL function.

* Second, it allows later to rollout this type to other application and have a generic way of TLS/mTLS configuration

* Fixes bug with tlsAssets mount with custom config reloader for alertmanager. Previously it was not mounted correctly and may cause issues with inaccessible assets.

related issues:
- #994
- #1033

Signed-off-by: f41gh7 <[email protected]>
  • Loading branch information
f41gh7 authored Jul 26, 2024
1 parent 10f48a6 commit 569fc52
Show file tree
Hide file tree
Showing 12 changed files with 842 additions and 30 deletions.
40 changes: 35 additions & 5 deletions api/operator/v1beta1/vmalertmanager_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ type VMAlertmanagerSpec struct {
// drops not needed security permissions
// +optional
UseStrictSecurity *bool `json:"useStrictSecurity,omitempty"`

// WebConfig defines configuration for webserver
// https://github.com/prometheus/alertmanager/blob/main/docs/https.md
WebConfig *AlertmanagerWebConfig `json:"webConfig,omitempty"`
}

// UnmarshalJSON implements json.Unmarshaler interface
Expand Down Expand Up @@ -409,6 +413,7 @@ func (cr VMAlertmanager) GetNSName() string {
return cr.GetNamespace()
}

// AsURL returns url for accessing alertmanager
func (cr *VMAlertmanager) AsURL() string {
port := "9093"
if cr.Spec.ServiceSpec != nil && cr.Spec.ServiceSpec.UseAsDefault {
Expand All @@ -419,11 +424,12 @@ func (cr *VMAlertmanager) AsURL() string {
}
}
}
return fmt.Sprintf("http://%s.%s.svc:%s", cr.PrefixedName(), cr.Namespace, port)

return fmt.Sprintf("%s://%s.%s.svc:%s", strings.ToLower(cr.ProbeScheme()), cr.PrefixedName(), cr.Namespace, port)
}

func (cr *VMAlertmanager) AsPodFQDN(idx int) string {
return fmt.Sprintf("http://%s-%d.%s.%s.svc:9093", cr.PrefixedName(), idx, cr.PrefixedName(), cr.Namespace)
func (cr *VMAlertmanager) asPodFQDN(idx int) string {
return fmt.Sprintf("%s://%s-%d.%s.%s.svc:9093", strings.ToLower(cr.ProbeScheme()), cr.PrefixedName(), idx, cr.PrefixedName(), cr.Namespace)
}

func (cr *VMAlertmanager) MetricPath() string {
Expand All @@ -447,7 +453,7 @@ func (cr *VMAlertmanager) AsNotifiers() []VMAlertNotifierSpec {
}
for i := 0; i < replicaCount; i++ {
ns := VMAlertNotifierSpec{
URL: cr.AsPodFQDN(i),
URL: cr.asPodFQDN(i),
}
r = append(r, ns)
}
Expand Down Expand Up @@ -484,8 +490,12 @@ func (cr *VMAlertmanager) ProbePort() string {
return cr.Spec.PortName
}

// ProbeScheme returns scheme for probe
func (cr *VMAlertmanager) ProbeScheme() string {
return strings.ToUpper(protoFromFlags(cr.Spec.ExtraArgs))
if cr.Spec.WebConfig != nil && cr.Spec.WebConfig.TLSServerConfig != nil {
return "HTTPS"
}
return "HTTP"
}

func (cr *VMAlertmanager) ProbeNeedLiveness() bool {
Expand Down Expand Up @@ -550,6 +560,26 @@ func (cr *VMAlertmanager) SetUpdateStatusTo(ctx context.Context, r client.Client
return nil
}

// AlertmanagerWebConfig defines web server configuration for alertmanager
type AlertmanagerWebConfig struct {
// TLSServerConfig defines tls configuration for alertmanager web server
TLSServerConfig *WebserverTLSConfig `json:"tls_server_config,omitempty"`
// HTTPServerConfig defines http server configuration for alertmanager web server
HTTPServerConfig *AlertmanagerHTTPConfig `json:"http_server_config,omitempty"`
// BasicAuthUsers Usernames and hashed passwords that have full access to the web server
// Passwords must be hashed with bcrypt
BasicAuthUsers map[string]string `json:"basic_auth_users,omitempty"`
}

// AlertmanagerHTTPConfig defines http server configuration for alertmanager
type AlertmanagerHTTPConfig struct {
// HTTP2 enables HTTP/2 support. Note that HTTP/2 is only supported with TLS.
// This can not be changed on the fly.
HTTP2 bool `json:"http2,omitempty"`
// Headers defines list of headers that can be added to HTTP responses.
Headers map[string]string `json:"headers,omitempty"`
}

// GetAdditionalService returns AdditionalServiceSpec settings
func (cr *VMAlertmanager) GetAdditionalService() *AdditionalServiceSpec {
return cr.Spec.ServiceSpec
Expand Down
24 changes: 24 additions & 0 deletions api/operator/v1beta1/vmalertmanager_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ func (r *VMAlertmanager) SetupWebhookWithManager(mgr ctrl.Manager) error {
var _ webhook.Validator = &VMAlertmanager{}

func (r *VMAlertmanager) sanityCheck() error {
if r.Spec.ConfigSecret == r.ConfigSecretName() {
return fmt.Errorf("spec.configSecret uses the same name as built-in config secret used by operator. Please change it's name")
}
if r.Spec.WebConfig != nil {
if r.Spec.WebConfig.HTTPServerConfig != nil {
if r.Spec.WebConfig.HTTPServerConfig.HTTP2 && r.Spec.WebConfig.TLSServerConfig == nil {
return fmt.Errorf("with enabled http2 for webserver, tls_server_config must be defined")
}
}
if r.Spec.WebConfig.TLSServerConfig != nil {
tc := r.Spec.WebConfig.TLSServerConfig
if tc.CertFile == "" && tc.CertSecretRef == nil {
return fmt.Errorf("either cert_secret_ref or cert_file must be set for tls_server_config")
}
if tc.KeyFile == "" && tc.KeySecretRef == nil {
return fmt.Errorf("either key_secret_ref or key_file must be set for tls_server_config")
}
if tc.ClientAuthType == "RequireAndVerifyClientCert" {
if tc.ClientCAFile == "" && tc.ClientCASecretRef == nil {
return fmt.Errorf("either client_ca_secret_ref or client_ca_file must be set for tls_server_config with enabled RequireAndVerifyClientCert")
}
}
}
}
return nil
}

Expand Down
43 changes: 43 additions & 0 deletions api/operator/v1beta1/vmextra_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -898,3 +898,46 @@ func (c *TLSConfig) BuildAssetPath(prefix, name, key string) string {
}
return fmt.Sprintf("%s_%s_%s", prefix, name, key)
}

// WebserverTLSConfig defines TLS configuration for the applications webserver
type WebserverTLSConfig struct {
// ClientAuthType defines server policy for client authentication
// If you want to enable client authentication (aka mTLS), you need to use RequireAndVerifyClientCert
// Note, mTLS is supported only at enterprise version of VictoriaMetrics components
// +kubebuilder:validation:Enum=NoClientCert;RequireAndVerifyClientCert
ClientAuthType string `json:"client_auth_type,omitempty"`

// ClientCA defines reference for secret with CA content under given key
// mutually exclusive with ClientCAFile
ClientCASecretRef *v1.SecretKeySelector `json:"client_ca_secret_ref,omitempty"`
// ClientCAFile defines path to the pre-mounted file with CA
// mutually exclusive with ClientCASecretRef
ClientCAFile string `json:"client_ca_file,omitempty"`
// Cert defines reference for secret with CA content under given key
// mutually exclusive with CertFile
CertSecretRef *v1.SecretKeySelector `json:"cert_secret_ref,omitempty"`
// CertFile defines path to the pre-mounted file with certificate
// mutually exclusive with CertSecretRef
CertFile string `json:"cert_file,omitempty"`
// Key defines reference for secret with certificate key content under given key
// mutually exclusive with KeyFile
KeySecretRef *v1.SecretKeySelector `json:"key_secret_ref,omitempty"`
// KeyFile defines path to the pre-mounted file with certificate key
// mutually exclusive with KeySecretRef
KeyFile string `json:"key_file,omitempty"`
// MinVersion minimum TLS version that is acceptable.
// +kubebuilder:validation:Enum=TLS10;TLS11;TLS12;TLS13
MinVersion string `json:"min_version,omitempty"`
// MaxVersion maximum TLS version that is acceptable.
// +kubebuilder:validation:Enum=TLS10;TLS11;TLS12;TLS13
MaxVersion string `json:"max_version,omitempty"`
// CipherSuites defines list of supported cipher suites for TLS versions up to TLS 1.2
// https://golang.org/pkg/crypto/tls/#pkg-constants
CipherSuites []string `json:"cipher_suites,omitempty"`
// CurvePreferences defines elliptic curves that will be used in an ECDHE handshake, in preference order.
// https://golang.org/pkg/crypto/tls/#CurveID
CurvePreferences []string `json:"curve_preferences,omitempty"`
// PreferServerCipherSuites controls whether the server selects the
// client's most preferred ciphersuite
PreferServerCipherSuites bool `json:"prefer_server_cipher_suites,omitempty"`
}
99 changes: 99 additions & 0 deletions api/operator/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 569fc52

Please sign in to comment.