Skip to content

Commit

Permalink
Merge pull request #193 from jcmoraisjr/jm-stats-ssl
Browse files Browse the repository at this point in the history
Add stats-ssl-cert configmap option
  • Loading branch information
jcmoraisjr authored Jul 26, 2018
2 parents 5b223f3 + 7d1ecaa commit 06f3b16
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 14 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ configmap with `haproxy.tmpl` key mounting into `/etc/haproxy/template` will wor
The following annotations are supported:

* `[0]` only in `canary` tag
* `[1]` only in `snapshot` tag

||Name|Data|Usage|
|---|---|---|:---:|
Expand Down Expand Up @@ -253,6 +254,7 @@ A ConfigMap can be created with `kubectl create configmap`.
The following parameters are supported:

* `[0]` only in `canary` tag
* `[1]` only in `snapshot` tag

||Name|Type|Default|
|---|---|---|---|
Expand Down Expand Up @@ -296,6 +298,7 @@ The following parameters are supported:
||[`stats-auth`](#stats)|user:passwd|no auth|
||[`stats-port`](#stats)|port number|`1936`|
||[`stats-proxy-protocol`](#stats)|[true\|false]|`false`|
|`[1]`|[`stats-ssl-cert`](#stats)|namespace/secret name|no ssl/plain http|
||[`syslog-endpoint`](#syslog-endpoint)|IP:port (udp)|do not log|
||[`tcp-log-format`](#log-format)|tcp log format|HAProxy default log format|
||[`timeout-client-fin`](#timeout)|time with suffix|`50s`|
Expand Down Expand Up @@ -545,11 +548,12 @@ to https if TLS is [configured](https://github.com/kubernetes/ingress/tree/maste

### stats

Configurations of the HAProxy status page:
Configurations of the HAProxy statistics page:

* `stats-auth`: Enable basic authentication with clear-text password - `<user>:<passwd>`
* `stats-port`: Change the port HAProxy should listen to requests
* `stats-proxy-protocol`: Define if the stats endpoint should enforce the PROXY protocol
* `stats-ssl-cert`: Optional namespace/secret-name of `tls.crt` and `tls.key` pair used to enable SSL on stats page. Plain http will be used if not provided, the secret wasn't found or the secret doesn't have a crt/key pair.

### syslog-endpoint

Expand Down
30 changes: 18 additions & 12 deletions pkg/common/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -739,27 +739,33 @@ func (ic *GenericController) getBackendServers(ingresses []*extensions.Ingress)

// GetAuthCertificate is used by the auth-tls annotations to get a cert from a secret
func (ic GenericController) GetAuthCertificate(name string) (*resolver.AuthSSLCert, error) {
if _, exists := ic.sslCertTracker.Get(name); !exists {
ic.syncSecret(name)
}

_, err := ic.listers.Secret.GetByName(name)
cert, err := ic.GetCertificate(name)
if err != nil {
return &resolver.AuthSSLCert{}, fmt.Errorf("unexpected error: %v", err)
return &resolver.AuthSSLCert{}, err
}

bc, exists := ic.sslCertTracker.Get(name)
if !exists {
return &resolver.AuthSSLCert{}, fmt.Errorf("secret %v does not exist", name)
}
cert := bc.(*ingress.SSLCert)
return &resolver.AuthSSLCert{
Secret: name,
CAFileName: cert.CAFileName,
PemSHA: cert.PemSHA,
}, nil
}

// GetCertificate get a SSLCert object from a secret name
func (ic *GenericController) GetCertificate(name string) (*ingress.SSLCert, error) {
crt, exists := ic.sslCertTracker.Get(name)
if !exists {
ic.syncSecret(name)
crt, exists = ic.sslCertTracker.Get(name)
}
if exists {
return crt.(*ingress.SSLCert), nil
}
if _, err := ic.listers.Secret.GetByName(name); err != nil {
return nil, err
}
return nil, fmt.Errorf("secret '%v' have neither ca.crt nor tls.crt/tls.key pair", name)
}

// GetFullResourceName add the currentNamespace prefix if name doesn't provide one
// and AllowCrossNamespace is allowing this
func (ic GenericController) GetFullResourceName(name, currentNamespace string) string {
Expand Down
8 changes: 8 additions & 0 deletions pkg/common/ingress/types_equals.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,3 +513,11 @@ func (l4b1 *ProxyProtocol) Equal(l4b2 *ProxyProtocol) bool {
}
return true
}

// Equal tests for equality between two SSLCert types
func (c1 *SSLCert) Equal(c2 *SSLCert) bool {
if c1.PemSHA != c2.PemSHA {
return false
}
return true
}
15 changes: 15 additions & 0 deletions pkg/controller/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func newControllerConfig(ingressConfig *ingress.Configuration, haproxyController
UDPEndpoints: cfg.ingress.UDPEndpoints,
PassthroughBackends: cfg.ingress.PassthroughBackends,
HAPassthrough: cfg.haPassthrough,
StatsSSLCert: cfg.statsSSLCert(),
Cfg: cfg.haproxyConfig,
DNSResolvers: cfg.DNSResolvers,
}, nil
Expand Down Expand Up @@ -124,6 +125,7 @@ func newHAProxyConfig(haproxyController *HAProxyController) *types.HAProxyConfig
HTTPStoHTTPPort: 0,
StatsPort: 1936,
StatsAuth: "",
StatsSSLCert: "",
CookieKey: "Ingress",
DynamicScaling: false,
StatsSocket: "/var/run/haproxy-stats.sock",
Expand Down Expand Up @@ -225,6 +227,19 @@ func (cfg *haConfig) createDNSResolvers() {
cfg.DNSResolvers = resolvers
}

func (cfg *haConfig) statsSSLCert() *ingress.SSLCert {
secretName := cfg.haproxyConfig.StatsSSLCert
if secretName == "" {
return &ingress.SSLCert{}
}
sslCert, err := cfg.haproxyController.controller.GetCertificate(secretName)
if err != nil {
glog.Warningf("error loading stats cert/key: %v", err)
return &ingress.SSLCert{}
}
return sslCert
}

func (cfg *haConfig) createHAProxyServers() {
haServers := make([]*types.HAProxyServer, 0, len(cfg.ingress.Servers))
haPassthrough := make([]*types.HAProxyPassthrough, 0, len(cfg.ingress.PassthroughBackends))
Expand Down
3 changes: 3 additions & 0 deletions pkg/types/equal.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,8 @@ func (c1 *ControllerConfig) Equal(c2 *ControllerConfig) bool {
if !reflect.DeepEqual(c1.Cfg, c2.Cfg) {
return false
}
if !c1.StatsSSLCert.Equal(c2.StatsSSLCert) {
return false
}
return true
}
2 changes: 2 additions & 0 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type (
UDPEndpoints []ingress.L4Service
PassthroughBackends []*ingress.SSLPassthroughBackend
HAPassthrough []*HAProxyPassthrough
StatsSSLCert *ingress.SSLCert
Cfg *HAProxyConfig
BackendSlots map[string]*HAProxyBackendSlots
DNSResolvers map[string]dnsresolvers.DNSResolver
Expand Down Expand Up @@ -77,6 +78,7 @@ type (
HTTPStoHTTPPort int `json:"https-to-http-port"`
StatsPort int `json:"stats-port"`
StatsAuth string `json:"stats-auth"`
StatsSSLCert string `json:"stats-ssl-cert"`
CookieKey string `json:"cookie-key"`
DynamicScaling bool `json:"dynamic-scaling"`
StatsSocket string
Expand Down
6 changes: 5 additions & 1 deletion rootfs/etc/haproxy/template/haproxy.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,11 @@ listen error503noendpoints
###### Stats page
######
listen stats
bind {{ $cfg.BindIPAddrStats }}:{{ $cfg.StatsPort }}{{ if $cfg.StatsProxyProtocol }} accept-proxy{{ end }}
{{- $ssl := $ing.StatsSSLCert }}
{{- if ne $ssl.PemSHA "" }}
# CRT PEM checksum: {{ $ssl.PemSHA }}
{{- end }}
bind {{ $cfg.BindIPAddrStats }}:{{ $cfg.StatsPort }}{{ if ne $ssl.PemFileName "" }} ssl crt {{ $ssl.PemFileName }}{{ end }}{{ if $cfg.StatsProxyProtocol }} accept-proxy{{ end }}
mode http
stats enable
stats realm HAProxy\ Statistics
Expand Down

0 comments on commit 06f3b16

Please sign in to comment.