Skip to content

Commit 68904d1

Browse files
Merge pull request #358 from jottofar/bug-1809195
Bug 1809195: Send CVO metrics over https
2 parents febb0aa + 874104a commit 68904d1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+9100
-411
lines changed

cmd/start.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@ func init() {
3030
cmd.PersistentFlags().BoolVar(&opts.EnableAutoUpdate, "enable-auto-update", opts.EnableAutoUpdate, "Enables the autoupdate controller.")
3131
cmd.PersistentFlags().BoolVar(&opts.EnableDefaultClusterVersion, "enable-default-cluster-version", opts.EnableDefaultClusterVersion, "Allows the operator to create a ClusterVersion object if one does not already exist.")
3232
cmd.PersistentFlags().StringVar(&opts.ReleaseImage, "release-image", opts.ReleaseImage, "The Openshift release image url.")
33+
cmd.PersistentFlags().StringVar(&opts.ServingCertFile, "serving-cert-file", opts.ServingCertFile, "The X.509 certificate file for serving metrics over HTTPS. You must set both --serving-cert-file and --serving-key-file, or neither.")
34+
cmd.PersistentFlags().StringVar(&opts.ServingKeyFile, "serving-key-file", opts.ServingKeyFile, "The X.509 key file for serving metrics over HTTPS. You must set both --serving-cert-file and --serving-key-file, or neither.")
3335
rootCmd.AddCommand(cmd)
3436
}

go.mod

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,34 @@ go 1.13
44

55
require (
66
github.com/blang/semver v3.5.0+incompatible
7+
github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292
78
github.com/davecgh/go-spew v1.1.1
89
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
910
github.com/ghodss/yaml v1.0.0
10-
github.com/gogo/protobuf v1.3.0 // indirect
1111
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect
1212
github.com/google/go-cmp v0.3.1 // indirect
1313
github.com/google/uuid v1.1.1
1414
github.com/googleapis/gnostic v0.3.1 // indirect
1515
github.com/hashicorp/golang-lru v0.5.3 // indirect
1616
github.com/imdario/mergo v0.3.8 // indirect
17-
github.com/openshift/api v0.0.0-20191028120151-c556078b427f
18-
github.com/openshift/client-go v0.0.0-20191001081553-3b0e988f8cb0
17+
github.com/openshift/api v0.0.0-20200210091934-a0e53e94816b
18+
github.com/openshift/client-go v0.0.0-20200116152001-92a2713fa240
19+
github.com/openshift/library-go v0.0.0-20200303185131-81598fff9efa
1920
github.com/pkg/errors v0.8.1
2021
github.com/prometheus/client_golang v1.1.0
2122
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4
2223
github.com/prometheus/common v0.7.0 // indirect
2324
github.com/prometheus/procfs v0.0.5 // indirect
2425
github.com/spf13/cobra v0.0.5
25-
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc
26+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
2627
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c // indirect
2728
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0
2829
google.golang.org/appengine v1.6.4 // indirect
2930
k8s.io/api v0.17.3
30-
k8s.io/apiextensions-apiserver v0.17.0
31+
k8s.io/apiextensions-apiserver v0.17.1
3132
k8s.io/apimachinery v0.17.3
3233
k8s.io/client-go v0.17.3
3334
k8s.io/klog v1.0.0
34-
k8s.io/kube-aggregator v0.17.0
35+
k8s.io/kube-aggregator v0.17.1
3536
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f
3637
)

go.sum

Lines changed: 69 additions & 23 deletions
Large diffs are not rendered by default.

install/0000_00_cluster-version-operator_03_deployment.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ spec:
2626
- "--release-image={{.ReleaseImage}}"
2727
- "--enable-auto-update=false"
2828
- "--enable-default-cluster-version=true"
29+
- "--serving-cert-file=/etc/tls/serving-cert/tls.crt"
30+
- "--serving-key-file=/etc/tls/serving-cert/tls.key"
2931
- "--v=4"
3032
resources:
3133
requests:
@@ -39,6 +41,9 @@ spec:
3941
- mountPath: /etc/cvo/updatepayloads
4042
name: etc-cvo-updatepayloads
4143
readOnly: true
44+
- mountPath: /etc/tls/serving-cert
45+
name: serving-cert
46+
readOnly: true
4247
env:
4348
- name: KUBERNETES_SERVICE_PORT # allows CVO to communicate with apiserver directly on same host.
4449
value: "6443"
@@ -80,3 +85,6 @@ spec:
8085
- name: etc-cvo-updatepayloads
8186
hostPath:
8287
path: /etc/cvo/updatepayloads
88+
- name: serving-cert
89+
secret:
90+
secretName: cluster-version-operator-serving-cert

install/0000_90_cluster-version-operator_02_servicemonitor.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ metadata:
99
exclude.release.openshift.io/internal-openshift-hosted: "true"
1010
spec:
1111
endpoints:
12+
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
1213
- interval: 30s
1314
port: metrics
14-
scheme: http
15+
scheme: https
16+
tlsConfig:
17+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
18+
serverName: cluster-version-operator.openshift-cluster-version.svc
1519
namespaceSelector:
1620
matchNames:
1721
- openshift-cluster-version

pkg/start/start.go

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ package start
44

55
import (
66
"context"
7+
"crypto/tls"
78
"fmt"
9+
"io/ioutil"
810
"math/rand"
11+
"net"
912
"net/http"
1013
"os"
1114
"os/signal"
1215
"sync"
1316
"syscall"
1417
"time"
1518

19+
"github.com/cockroachdb/cmux"
20+
1621
"github.com/google/uuid"
1722
"github.com/prometheus/client_golang/prometheus/promhttp"
1823
v1 "k8s.io/api/core/v1"
@@ -34,6 +39,7 @@ import (
3439
"github.com/openshift/cluster-version-operator/pkg/autoupdate"
3540
"github.com/openshift/cluster-version-operator/pkg/cvo"
3641
"github.com/openshift/cluster-version-operator/pkg/internal"
42+
"github.com/openshift/library-go/pkg/crypto"
3743
)
3844

3945
const (
@@ -49,7 +55,9 @@ const (
4955

5056
// Options are the valid inputs to starting the CVO.
5157
type Options struct {
52-
ReleaseImage string
58+
ReleaseImage string
59+
ServingCertFile string
60+
ServingKeyFile string
5361

5462
Kubeconfig string
5563
NodeName string
@@ -103,6 +111,12 @@ func (o *Options) Run() error {
103111
if o.ReleaseImage == "" {
104112
return fmt.Errorf("missing --release-image flag, it is required")
105113
}
114+
if o.ServingCertFile == "" && o.ServingKeyFile != "" {
115+
return fmt.Errorf("--serving-key-file was set, so --serving-cert-file must also be set")
116+
}
117+
if o.ServingKeyFile == "" && o.ServingCertFile != "" {
118+
return fmt.Errorf("--serving-cert-file was set, so --serving-key-file must also be set")
119+
}
106120
if len(o.PayloadOverride) > 0 {
107121
klog.Warningf("Using an override payload directory for testing only: %s", o.PayloadOverride)
108122
}
@@ -153,16 +167,79 @@ func (o *Options) Run() error {
153167
return nil
154168
}
155169

170+
func (o *Options) makeTLSConfig() (*tls.Config, error) {
171+
// Load the initial certificate contents.
172+
certBytes, err := ioutil.ReadFile(o.ServingCertFile)
173+
if err != nil {
174+
return nil, err
175+
}
176+
keyBytes, err := ioutil.ReadFile(o.ServingKeyFile)
177+
if err != nil {
178+
return nil, err
179+
}
180+
certificate, err := tls.X509KeyPair(certBytes, keyBytes)
181+
if err != nil {
182+
return nil, err
183+
}
184+
185+
return crypto.SecureTLSConfig(&tls.Config{
186+
GetCertificate: func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
187+
return &certificate, nil
188+
},
189+
}), nil
190+
}
191+
156192
func (o *Options) run(ctx context.Context, controllerCtx *Context, lock *resourcelock.ConfigMapLock) {
157193
// listen on metrics
158194
if len(o.ListenAddr) > 0 {
159-
mux := http.NewServeMux()
160-
mux.Handle("/metrics", promhttp.Handler())
195+
handler := http.NewServeMux()
196+
handler.Handle("/metrics", promhttp.Handler())
197+
tcpl, err := net.Listen("tcp", o.ListenAddr)
198+
if err != nil {
199+
klog.Fatalf("Listen error: %v", err)
200+
}
201+
202+
// if a TLS connection was requested, set up a connection mux that will send TLS requests to
203+
// the TLS server but send HTTP requests to the HTTP server. Preserves the ability for legacy
204+
// HTTP, needed during upgrade, while still allowing TLS certs and end to end metrics protection.
205+
m := cmux.New(tcpl)
206+
207+
// match HTTP first
208+
httpl := m.Match(cmux.HTTP1())
161209
go func() {
162-
if err := http.ListenAndServe(o.ListenAddr, mux); err != nil {
163-
klog.Fatalf("Unable to start metrics server: %v", err)
210+
s := &http.Server{
211+
Handler: handler,
212+
}
213+
if err := s.Serve(httpl); err != cmux.ErrListenerClosed {
214+
klog.Fatalf("HTTP serve error: %v", err)
164215
}
165216
}()
217+
218+
if o.ServingCertFile != "" || o.ServingKeyFile != "" {
219+
tlsConfig, err := o.makeTLSConfig()
220+
if err != nil {
221+
klog.Fatalf("Failed to create TLS config: %v", err)
222+
}
223+
224+
tlsListener := tls.NewListener(m.Match(cmux.Any()), tlsConfig)
225+
klog.Infof("Metrics port listening for HTTP and HTTPS on %v", o.ListenAddr)
226+
go func() {
227+
s := &http.Server{
228+
Handler: handler,
229+
}
230+
if err := s.Serve(tlsListener); err != cmux.ErrListenerClosed {
231+
klog.Fatalf("HTTPS serve error: %v", err)
232+
}
233+
}()
234+
235+
go func() {
236+
if err := m.Serve(); err != nil {
237+
klog.Errorf("CMUX serve error: %v", err)
238+
}
239+
}()
240+
} else {
241+
klog.Infof("Metrics port listening for HTTP on %v", o.ListenAddr)
242+
}
166243
}
167244

168245
exit := make(chan struct{})

vendor/github.com/cockroachdb/cmux/.gitignore

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/cockroachdb/cmux/.travis.yml

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/cockroachdb/cmux/CONTRIBUTORS

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)