Skip to content
This repository was archived by the owner on Nov 7, 2022. It is now read-only.

Commit 9b5a4ab

Browse files
committed
cmd: occollector, ocagent: add TLS for OpenCensus receiver
With this change, one can now optionally start either the occollector or ocagent with TLS credentials pointing to a certificate file and a key file in the form of: ```yaml receivers: opencensus: tls_credentials: cert_file: "cert.pem" key_file: "key.pem" ``` Despite the code changes for starting the receiver always passing in `tlsCredsOption`, if no TLS Configuration is parsed, the OpenCensus receiver Option passed in will be a noop. Fixes #367
1 parent 9480295 commit 9b5a4ab

10 files changed

Lines changed: 315 additions & 17 deletions

File tree

cmd/ocagent/main.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func runOCAgent() {
102102
commonMetricsSink := exporter.MultiMetricsExporters(metricsExporters...)
103103

104104
// Add other receivers here as they are implemented
105-
ocReceiverDoneFn, err := runOCReceiver(agentConfig, commonSpanSink, commonMetricsSink)
105+
ocReceiverDoneFn, err := runOCReceiver(logger, agentConfig, commonSpanSink, commonMetricsSink)
106106
if err != nil {
107107
log.Fatal(err)
108108
}
@@ -189,16 +189,24 @@ func runZPages(port int) func() error {
189189
return srv.Close
190190
}
191191

192-
func runOCReceiver(acfg *config.Config, sr receiver.TraceReceiverSink, mr receiver.MetricsReceiverSink) (doneFn func() error, err error) {
192+
func runOCReceiver(logger *zap.Logger, acfg *config.Config, sr receiver.TraceReceiverSink, mr receiver.MetricsReceiverSink) (doneFn func() error, err error) {
193+
tlsCredsOption, hasTLSCreds, err := acfg.OpenCensusReceiverTLSCredentialsServerOption()
194+
if err != nil {
195+
return nil, fmt.Errorf("OpenCensus receiver TLS Credentials: %v", err)
196+
}
193197
addr := acfg.OpenCensusReceiverAddress()
194198
corsOrigins := acfg.OpenCensusReceiverCorsAllowedOrigins()
195-
ocr, err := opencensusreceiver.New(addr, opencensusreceiver.WithCorsOrigins(corsOrigins))
199+
ocr, err := opencensusreceiver.New(addr,
200+
tlsCredsOption,
201+
opencensusreceiver.WithCorsOrigins(corsOrigins))
202+
196203
if err != nil {
197204
return nil, fmt.Errorf("Failed to create the OpenCensus receiver on address %q: error %v", addr, err)
198205
}
199206
if err := view.Register(internal.AllViews...); err != nil {
200207
return nil, fmt.Errorf("Failed to register internal.AllViews: %v", err)
201208
}
209+
202210
// Temporarily disabling the grpc metrics since they do not provide good data at this moment,
203211
// See https://github.com/census-instrumentation/opencensus-service/issues/287
204212
// if err := view.Register(ocgrpc.DefaultServerViews...); err != nil {
@@ -227,6 +235,13 @@ func runOCReceiver(acfg *config.Config, sr receiver.TraceReceiverSink, mr receiv
227235
log.Printf("Running OpenCensus Metrics receiver as a gRPC service at %q", addr)
228236
}
229237

238+
if hasTLSCreds {
239+
tlsCreds := acfg.OpenCensusReceiverTLSServerCredentials()
240+
logger.Info("OpenCensus receiver with TLS Credentials",
241+
zap.String("cert_file", tlsCreds.CertFile),
242+
zap.String("key_file", tlsCreds.KeyFile))
243+
}
244+
230245
doneFn = ocr.Stop
231246
return doneFn, nil
232247
}

cmd/occollector/app/builder/builder.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"strings"
2121

22+
"github.com/census-instrumentation/opencensus-service/internal/config"
2223
"github.com/spf13/viper"
2324
)
2425

@@ -102,6 +103,9 @@ func (cfg *JaegerReceiverCfg) InitFromViper(v *viper.Viper) (*JaegerReceiverCfg,
102103
type OpenCensusReceiverCfg struct {
103104
// Port is the port that the receiver will use
104105
Port int `mapstructure:"port"`
106+
107+
// TLSCredentials is a (cert_file, key_file) configuration.
108+
TLSCredentials *config.TLSCredentials `mapstructure:"tls_credentials"`
105109
}
106110

107111
// OpenCensusReceiverEnabled checks if the OpenCensus receiver is enabled, via a command-line flag, environment

internal/collector/opencensus/receiver.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@ func Start(logger *zap.Logger, v *viper.Viper, spanProc processor.SpanProcessor)
3737
return nil, err
3838
}
3939

40-
addr := ":" + strconv.FormatInt(int64(rOpts.Port), 10)
40+
tlsCredsOption, hasTLSCreds, err := rOpts.TLSCredentials.ToOpenCensusReceiverServerOption()
41+
if err != nil {
42+
return nil, fmt.Errorf("OpenCensus receiver TLS Credentials: %v", err)
43+
}
4144

42-
ocr, err := opencensusreceiver.New(addr)
45+
addr := ":" + strconv.FormatInt(int64(rOpts.Port), 10)
46+
ocr, err := opencensusreceiver.New(addr, tlsCredsOption)
4347
if err != nil {
4448
return nil, fmt.Errorf("Failed to create the OpenCensus trace receiver: %v", err)
4549
}
@@ -48,7 +52,15 @@ func Start(logger *zap.Logger, v *viper.Viper, spanProc processor.SpanProcessor)
4852
return nil, fmt.Errorf("Cannot bind Opencensus receiver to address %q: %v", addr, err)
4953
}
5054

51-
logger.Info("OpenCensus receiver is running.", zap.Int("port", rOpts.Port))
55+
if hasTLSCreds {
56+
tlsCreds := rOpts.TLSCredentials
57+
logger.Info("OpenCensus receiver is running.",
58+
zap.Int("port", rOpts.Port),
59+
zap.String("cert_file", tlsCreds.CertFile),
60+
zap.String("key_file", tlsCreds.KeyFile))
61+
} else {
62+
logger.Info("OpenCensus receiver is running.", zap.Int("port", rOpts.Port))
63+
}
5264

5365
return ocr, nil
5466
}

internal/config/config.go

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323

2424
"github.com/spf13/viper"
2525
"go.uber.org/zap"
26+
"google.golang.org/grpc"
27+
"google.golang.org/grpc/credentials"
2628
yaml "gopkg.in/yaml.v2"
2729

2830
"github.com/census-instrumentation/opencensus-service/exporter"
@@ -35,6 +37,7 @@ import (
3537
"github.com/census-instrumentation/opencensus-service/exporter/prometheusexporter"
3638
"github.com/census-instrumentation/opencensus-service/exporter/stackdriverexporter"
3739
"github.com/census-instrumentation/opencensus-service/exporter/zipkinexporter"
40+
"github.com/census-instrumentation/opencensus-service/receiver/opencensusreceiver"
3841
"github.com/census-instrumentation/opencensus-service/receiver/prometheusreceiver"
3942
)
4043

@@ -131,6 +134,9 @@ type ReceiverConfig struct {
131134
DisableTracing bool `yaml:"disable_tracing"`
132135
// DisableMetrics disables metrics receiving and is only applicable to metrics receivers.
133136
DisableMetrics bool `yaml:"disable_metrics"`
137+
138+
// TLSCredentials is a (cert_file, key_file) configuration.
139+
TLSCredentials *TLSCredentials `yaml:"tls_credentials"`
134140
}
135141

136142
// ScribeReceiverConfig carries the settings for the Zipkin Scribe receiver.
@@ -191,15 +197,21 @@ func (c *Config) OpenCensusReceiverCorsAllowedOrigins() []string {
191197
// CanRunOpenCensusTraceReceiver returns true if the configuration
192198
// permits running the OpenCensus Trace receiver.
193199
func (c *Config) CanRunOpenCensusTraceReceiver() bool {
194-
return c != nil && c.Receivers != nil &&
195-
c.Receivers.OpenCensus != nil && !c.Receivers.OpenCensus.DisableTracing
200+
return c.openCensusReceiverEnabled() && !c.Receivers.OpenCensus.DisableTracing
196201
}
197202

198203
// CanRunOpenCensusMetricsReceiver returns true if the configuration
199204
// permits running the OpenCensus Metrics receiver.
200205
func (c *Config) CanRunOpenCensusMetricsReceiver() bool {
206+
return c.openCensusReceiverEnabled() && !c.Receivers.OpenCensus.DisableMetrics
207+
}
208+
209+
// openCensusReceiverEnabled returns true if both:
210+
// Config.Receivers and Config.Receivers.OpenCensus
211+
// are non-nil.
212+
func (c *Config) openCensusReceiverEnabled() bool {
201213
return c != nil && c.Receivers != nil &&
202-
c.Receivers.OpenCensus != nil && !c.Receivers.OpenCensus.DisableMetrics
214+
c.Receivers.OpenCensus != nil
203215
}
204216

205217
// ZPagesDisabled returns true if zPages have not been enabled.
@@ -316,6 +328,53 @@ func (c *Config) JaegerReceiverPorts() (collectorPort, thriftPort int) {
316328
return jc.CollectorHTTPPort, jc.CollectorThriftPort
317329
}
318330

331+
// HasTLSCredentials returns true if TLSCredentials is non-nil
332+
func (rCfg *ReceiverConfig) HasTLSCredentials() bool {
333+
return rCfg != nil && rCfg.TLSCredentials != nil && rCfg.TLSCredentials.nonEmpty()
334+
}
335+
336+
// OpenCensusReceiverTLSServerCredentials retrieves the TLS credentials
337+
// from this Config's OpenCensus receiver if any.
338+
func (c *Config) OpenCensusReceiverTLSServerCredentials() *TLSCredentials {
339+
if !c.openCensusReceiverEnabled() {
340+
return nil
341+
}
342+
343+
ocrConfig := c.Receivers.OpenCensus
344+
if !ocrConfig.HasTLSCredentials() {
345+
return nil
346+
}
347+
return ocrConfig.TLSCredentials
348+
}
349+
350+
// ToOpenCensusReceiverServerOption checks if the TLS credentials
351+
// in the form of a certificate file and a key file. If they aren't,
352+
// it will return opencensusreceiver.WithNoopOption() and a nil error.
353+
// Otherwise, it will try to retrieve gRPC transport credentials from the file combinations,
354+
// and create a option, along with any errors encountered while retrieving the credentials.
355+
func (tlsCreds *TLSCredentials) ToOpenCensusReceiverServerOption() (opt opencensusreceiver.Option, ok bool, err error) {
356+
if tlsCreds == nil {
357+
return opencensusreceiver.WithNoopOption(), false, nil
358+
}
359+
360+
transportCreds, err := credentials.NewServerTLSFromFile(tlsCreds.CertFile, tlsCreds.KeyFile)
361+
if err != nil {
362+
return nil, false, err
363+
}
364+
gRPCCredsOpt := grpc.Creds(transportCreds)
365+
return opencensusreceiver.WithGRPCServerOptions(gRPCCredsOpt), true, nil
366+
}
367+
368+
// OpenCensusReceiverTLSCredentialsServerOption checks if the OpenCensus receiver's Configuration
369+
// has TLS credentials in the form of a certificate file and a key file. If it doesn't
370+
// have any, it will return opencensusreceiver.WithNoopOption() and a nil error.
371+
// Otherwise, it will try to retrieve gRPC transport credentials from the file combinations,
372+
// and create a option, along with any errors encountered while retrieving the credentials.
373+
func (c *Config) OpenCensusReceiverTLSCredentialsServerOption() (opt opencensusreceiver.Option, ok bool, err error) {
374+
tlsCreds := c.OpenCensusReceiverTLSServerCredentials()
375+
return tlsCreds.ToOpenCensusReceiverServerOption()
376+
}
377+
319378
// ParseOCAgentConfig unmarshals byte content in the YAML file format
320379
// to retrieve the configuration that will be used to run the OpenCensus agent.
321380
func ParseOCAgentConfig(yamlBlob []byte) (*Config, error) {

internal/config/tls_credentials.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2019, OpenCensus Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
// TLSCredentials holds the fields for TLS credentials
18+
// that are used for starting a server.
19+
type TLSCredentials struct {
20+
// CertFile is the file path containing the TLS certificate.
21+
CertFile string `yaml:"cert_file"`
22+
23+
// KeyFile is the file path containing the TLS key.
24+
KeyFile string `yaml:"key_file"`
25+
}
26+
27+
// nonEmpty returns true if the TLSCredentials are non-nil and
28+
// if either CertFile or KeyFile is non-empty.
29+
func (tc *TLSCredentials) nonEmpty() bool {
30+
return tc != nil && (tc.CertFile != "" || tc.KeyFile != "")
31+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright 2019, OpenCensus Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"reflect"
19+
"testing"
20+
)
21+
22+
func TestTLSConfigByParsing(t *testing.T) {
23+
configYAML := []byte(`
24+
receivers:
25+
opencensus:
26+
tls_credentials:
27+
cert_file: "foobar.crt"
28+
key_file: "foobar.key"
29+
`)
30+
31+
cfg, err := ParseOCAgentConfig(configYAML)
32+
if err != nil {
33+
t.Fatalf("Failed to parse OCAgent config: %v", err)
34+
}
35+
if cfg == nil {
36+
t.Fatal("Returned nil while parsing config")
37+
}
38+
39+
tlsCreds := cfg.OpenCensusReceiverTLSServerCredentials()
40+
if tlsCreds == nil {
41+
t.Error("Surprisingly turned out nil TLS credentials")
42+
}
43+
44+
if !tlsCreds.nonEmpty() {
45+
t.Error("nonEmpty returned false")
46+
}
47+
48+
want := &TLSCredentials{
49+
CertFile: "foobar.crt",
50+
KeyFile: "foobar.key",
51+
}
52+
53+
if !reflect.DeepEqual(tlsCreds, want) {
54+
t.Errorf("Got: %+v\nWant: %+v", cfg, want)
55+
}
56+
}
57+
58+
func TestTLSConfigDereferencing(t *testing.T) {
59+
var nilConfig *Config
60+
if g := nilConfig.OpenCensusReceiverTLSServerCredentials(); g != nil {
61+
t.Errorf("Retrieved non-nil TLSServerCredentials: %+v\n", g)
62+
}
63+
64+
if nilConfig.openCensusReceiverEnabled() {
65+
t.Error("Somehow OpenCensus receiver is enabled on a nil Config")
66+
}
67+
}
68+
69+
func TestTLSCredentials_nonEmptyChecks(t *testing.T) {
70+
// TLSCredentials are considered "nonEmpty" if at least either
71+
// of "cert_file" or "key_file" are non-empty.
72+
combinations := []struct {
73+
config string
74+
want bool
75+
}{
76+
{config: ``, want: false},
77+
{
78+
config: `
79+
receivers:
80+
opencensus:
81+
tls_credentials:
82+
cert_file: "foo"
83+
`, want: true,
84+
},
85+
{
86+
config: `
87+
receivers:
88+
opencensus:
89+
tls_credentials:
90+
key_file: "foo"
91+
`, want: true,
92+
},
93+
{
94+
config: `
95+
receivers:
96+
opencensus:
97+
tls_credentials:
98+
key_file: ""
99+
cert_file: ""
100+
`, want: false,
101+
},
102+
}
103+
104+
for i, tt := range combinations {
105+
cfg, err := ParseOCAgentConfig([]byte(tt.config))
106+
if err != nil {
107+
t.Errorf("#%d: unexpected parsing error: %v", i, err)
108+
}
109+
tlsCreds := cfg.OpenCensusReceiverTLSServerCredentials()
110+
got, want := tlsCreds.nonEmpty(), tt.want
111+
if got != want {
112+
t.Errorf("#%d: got=%t want=%t\nConfig:\n%s", i, got, want, tt.config)
113+
}
114+
}
115+
}

receiver/opencensusreceiver/opencensus.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ import (
3939

4040
// Receiver is the type that exposes Trace and Metrics reception.
4141
type Receiver struct {
42-
mu sync.Mutex
43-
ln net.Listener
44-
serverGRPC *grpc.Server
45-
serverHTTP *http.Server
46-
gatewayMux *gatewayruntime.ServeMux
47-
corsOrigins []string
42+
mu sync.Mutex
43+
ln net.Listener
44+
serverGRPC *grpc.Server
45+
serverHTTP *http.Server
46+
gatewayMux *gatewayruntime.ServeMux
47+
corsOrigins []string
48+
grpcServerOptions []grpc.ServerOption
4849

4950
traceReceiverOpts []octrace.Option
5051
metricsReceiverOpts []ocmetrics.Option
@@ -138,7 +139,7 @@ func (ocr *Receiver) grpcServer() *grpc.Server {
138139
defer ocr.mu.Unlock()
139140

140141
if ocr.serverGRPC == nil {
141-
ocr.serverGRPC = internal.GRPCServerWithObservabilityEnabled()
142+
ocr.serverGRPC = internal.GRPCServerWithObservabilityEnabled(ocr.grpcServerOptions...)
142143
}
143144

144145
return ocr.serverGRPC

receiver/opencensusreceiver/opencensus_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func runContentTypeTests(addr string, contentTypeDesignation bool, contentType s
262262
{
263263
TraceId: []byte{
264264
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
265-
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0X10,
265+
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
266266
},
267267
},
268268
},

0 commit comments

Comments
 (0)