diff --git a/receiver/kubeletstatsreceiver/README.md b/receiver/kubeletstatsreceiver/README.md index 9a4811dcd19c..ed12568f9f9f 100644 --- a/receiver/kubeletstatsreceiver/README.md +++ b/receiver/kubeletstatsreceiver/README.md @@ -23,6 +23,13 @@ TLS tells this receiver to use TLS for auth and requires that the fields ServiceAccount tells this receiver to use the default service account token to authenticate to the kubelet API. +Note: a missing or empty `endpoint` will cause the hostname on which the collector +is running to be used as the endpoint. If the hostNetwork flag is set, and the +collector is running in a pod, this hostname will resolve to the node's network +namespace. + +### TLS Example + ```yaml receivers: kubeletstats: @@ -42,3 +49,37 @@ service: receivers: [kubeletstats] exporters: [file] ``` + +### ServiceAccount Example + +Although it's possible to use kubernetes' hostNetwork feature to talk to the +kubelet api from a pod, the preferred approach is to use the downard API. + +Make sure the pod spec sets the node name as follows: + +```yaml +env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName +``` + +Then the otel config can reference the `K8S_NODE_NAME` environment variable: + +```yaml +receivers: + kubeletstats: + collection_interval: 20s + auth_type: "serviceAccount" + endpoint: "${K8S_NODE_NAME}:10250" + insecure_skip_verify: true +exporters: + file: + path: "fileexporter.txt" +service: + pipelines: + metrics: + receivers: [kubeletstats] + exporters: [file] +``` diff --git a/receiver/kubeletstatsreceiver/config_test.go b/receiver/kubeletstatsreceiver/config_test.go new file mode 100644 index 000000000000..943081b60365 --- /dev/null +++ b/receiver/kubeletstatsreceiver/config_test.go @@ -0,0 +1,78 @@ +// Copyright 2020, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubeletstatsreceiver + +import ( + "path" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/config/configtls" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/k8sconfig" + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kubeletstatsreceiver/kubelet" +) + +func TestLoadConfig(t *testing.T) { + factories, err := config.ExampleComponents() + require.NoError(t, err) + factory := &Factory{} + factories.Receivers[configmodels.Type(typeStr)] = factory + cfg, err := config.LoadConfigFile( + t, path.Join(".", "testdata", "config.yaml"), factories, + ) + require.NoError(t, err) + require.NotNil(t, cfg) + + tlsCfg := cfg.Receivers["kubeletstats/tls"].(*Config) + duration := 10 * time.Second + require.Equal(t, &Config{ + ReceiverSettings: configmodels.ReceiverSettings{ + TypeVal: "kubeletstats", + NameVal: "kubeletstats/tls", + Endpoint: "1.2.3.4:5555", + }, + ClientConfig: kubelet.ClientConfig{ + APIConfig: k8sconfig.APIConfig{ + AuthType: "tls", + }, + TLSSetting: configtls.TLSSetting{ + CAFile: "/path/to/ca.crt", + CertFile: "/path/to/apiserver.crt", + KeyFile: "/path/to/apiserver.key", + }, + InsecureSkipVerify: true, + }, + CollectionInterval: duration, + }, tlsCfg) + + saCfg := cfg.Receivers["kubeletstats/sa"].(*Config) + require.Equal(t, &Config{ + ReceiverSettings: configmodels.ReceiverSettings{ + TypeVal: "kubeletstats", + NameVal: "kubeletstats/sa", + }, + ClientConfig: kubelet.ClientConfig{ + APIConfig: k8sconfig.APIConfig{ + AuthType: "serviceAccount", + }, + InsecureSkipVerify: true, + }, + CollectionInterval: duration, + }, saCfg) +} diff --git a/receiver/kubeletstatsreceiver/go.mod b/receiver/kubeletstatsreceiver/go.mod index 904db9f1ab1b..d086ae6b05bb 100644 --- a/receiver/kubeletstatsreceiver/go.mod +++ b/receiver/kubeletstatsreceiver/go.mod @@ -7,6 +7,7 @@ require ( github.com/golang/protobuf v1.3.5 github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.0.0-00010101000000-000000000000 github.com/open-telemetry/opentelemetry-collector-contrib/receiver/redisreceiver v0.0.0-20200518175917-05cf2ea24e6c + github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.5.1 go.opentelemetry.io/collector v0.3.1-0.20200612184320-01ce74db9c44 go.uber.org/zap v1.10.0 diff --git a/receiver/kubeletstatsreceiver/kubelet/cert.go b/receiver/kubeletstatsreceiver/kubelet/cert.go index 0f2d5aed555b..c4e947d0becc 100644 --- a/receiver/kubeletstatsreceiver/kubelet/cert.go +++ b/receiver/kubeletstatsreceiver/kubelet/cert.go @@ -16,14 +16,15 @@ package kubelet import ( "crypto/x509" - "errors" "io/ioutil" + + "github.com/pkg/errors" ) func systemCertPoolPlusPath(certPath string) (*x509.CertPool, error) { sysCerts, err := x509.SystemCertPool() if err != nil { - return nil, err + return nil, errors.WithMessage(err, "Could not load system x509 cert pool") } return certPoolPlusPath(sysCerts, certPath) } @@ -31,7 +32,7 @@ func systemCertPoolPlusPath(certPath string) (*x509.CertPool, error) { func certPoolPlusPath(certPool *x509.CertPool, certPath string) (*x509.CertPool, error) { certBytes, err := ioutil.ReadFile(certPath) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "Cert path %s could not be read", certPath) } ok := certPool.AppendCertsFromPEM(certBytes) if !ok { diff --git a/receiver/kubeletstatsreceiver/kubelet/client.go b/receiver/kubeletstatsreceiver/kubelet/client.go index abd1022cdff2..527b100b2dff 100644 --- a/receiver/kubeletstatsreceiver/kubelet/client.go +++ b/receiver/kubeletstatsreceiver/kubelet/client.go @@ -20,41 +20,32 @@ import ( "fmt" "io/ioutil" "net/http" + "os" + "github.com/pkg/errors" "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/k8sconfig" ) -// Config for a kubelet Client. Mostly for talking to the kubelet HTTP endpoint. -type ClientConfig struct { - k8sconfig.APIConfig `mapstructure:",squash"` - // Path to the CA cert. For a client this verifies the server certificate. - // For a server this verifies client certificates. If empty uses system root CA. - // (optional) - CAFile string `mapstructure:"ca_file"` - // Path to the TLS cert to use for TLS required connections. (optional) - CertFile string `mapstructure:"cert_file"` - // Path to the TLS key to use for TLS required connections. (optional) - // TODO replace with open-telemetry/opentelemetry-collector#933 when done - KeyFile string `mapstructure:"key_file"` - // InsecureSkipVerify controls whether the client verifies the server's - // certificate chain and host name. - InsecureSkipVerify bool `mapstructure:"insecure_skip_verify"` -} +const svcAcctCACertPath = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" +const svcAcctTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token" type Client interface { Get(path string) ([]byte, error) } func NewClient(endpoint string, cfg *ClientConfig, logger *zap.Logger) (Client, error) { - if cfg.APIConfig.AuthType != k8sconfig.AuthTypeTLS { + switch cfg.APIConfig.AuthType { + case k8sconfig.AuthTypeTLS: + return newTLSClient(endpoint, cfg, logger) + case k8sconfig.AuthTypeServiceAccount: + return newServiceAccountClient(endpoint, svcAcctCACertPath, svcAcctTokenPath, logger) + default: return nil, fmt.Errorf("AuthType [%s] not supported", cfg.APIConfig.AuthType) } - return newTLSClient(endpoint, cfg, logger) } -// not unit tested func newTLSClient(endpoint string, cfg *ClientConfig, logger *zap.Logger) (Client, error) { rootCAs, err := systemCertPoolPlusPath(cfg.CAFile) if err != nil { @@ -64,44 +55,99 @@ func newTLSClient(endpoint string, cfg *ClientConfig, logger *zap.Logger) (Clien if err != nil { return nil, err } - return defaultTLSClient(endpoint, cfg.InsecureSkipVerify, rootCAs, clientCert, logger), nil + return defaultTLSClient( + endpoint, + cfg.InsecureSkipVerify, + rootCAs, + []tls.Certificate{clientCert}, + nil, + logger, + ) } -func defaultTLSClient(endpoint string, insecureSkipVerify bool, rootCAs *x509.CertPool, clientCert tls.Certificate, logger *zap.Logger) *tlsClient { +func newServiceAccountClient( + endpoint string, + caCertPath string, + tokenPath string, + logger *zap.Logger, +) (*clientImpl, error) { + rootCAs, err := systemCertPoolPlusPath(caCertPath) + if err != nil { + return nil, err + } + tok, err := ioutil.ReadFile(tokenPath) + if err != nil { + return nil, err + } + tr := defaultTransport() + tr.TLSClientConfig = &tls.Config{ + RootCAs: rootCAs, + } + return defaultTLSClient(endpoint, true, rootCAs, nil, tok, logger) +} + +func defaultTLSClient( + endpoint string, + insecureSkipVerify bool, + rootCAs *x509.CertPool, + certificates []tls.Certificate, + tok []byte, + logger *zap.Logger, +) (*clientImpl, error) { tr := defaultTransport() tr.TLSClientConfig = &tls.Config{ RootCAs: rootCAs, - Certificates: []tls.Certificate{clientCert}, + Certificates: certificates, InsecureSkipVerify: insecureSkipVerify, } - return &tlsClient{ + if endpoint == "" { + var err error + endpoint, err = defaultEndpoint() + if err != nil { + return nil, err + } + logger.Warn("Kubelet endpoint not defined, using default endpoint " + endpoint) + } + return &clientImpl{ baseURL: "https://" + endpoint, httpClient: http.Client{Transport: tr}, + tok: tok, logger: logger, + }, nil +} + +// This will work if hostNetwork is turned on, in which case the pod has access +// to the node's loopback device. +// https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces +func defaultEndpoint() (string, error) { + hostname, err := os.Hostname() + if err != nil { + return "", errors.WithMessage(err, "Unable to get hostname for default endpoint") } + const kubeletPort = "10250" + return hostname + ":" + kubeletPort, nil } func defaultTransport() *http.Transport { return http.DefaultTransport.(*http.Transport).Clone() } -// tlsClient +// clientImpl -var _ Client = (*tlsClient)(nil) +var _ Client = (*clientImpl)(nil) -type tlsClient struct { +type clientImpl struct { baseURL string httpClient http.Client logger *zap.Logger + tok []byte } -func (c *tlsClient) Get(path string) ([]byte, error) { - url := c.baseURL + path - req, err := http.NewRequest("GET", url, nil) +func (c *clientImpl) Get(path string) ([]byte, error) { + req, err := c.buildReq(path) if err != nil { return nil, err } - req.Header.Set("Content-Type", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return nil, err @@ -118,3 +164,16 @@ func (c *tlsClient) Get(path string) ([]byte, error) { } return body, nil } + +func (c *clientImpl) buildReq(path string) (*http.Request, error) { + url := c.baseURL + path + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + if c.tok != nil { + req.Header.Set("Authorization", fmt.Sprintf("bearer %s", c.tok)) + } + return req, nil +} diff --git a/receiver/kubeletstatsreceiver/kubelet/client_config.go b/receiver/kubeletstatsreceiver/kubelet/client_config.go new file mode 100644 index 000000000000..3a9e67da53a1 --- /dev/null +++ b/receiver/kubeletstatsreceiver/kubelet/client_config.go @@ -0,0 +1,30 @@ +// Copyright 2020, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubelet + +import ( + "go.opentelemetry.io/collector/config/configtls" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/k8sconfig" +) + +// Config for a kubelet client for talking to a kubelet HTTP endpoint. +type ClientConfig struct { + k8sconfig.APIConfig `mapstructure:",squash"` + configtls.TLSSetting `mapstructure:",squash"` + // InsecureSkipVerify controls whether the client verifies the server's + // certificate chain and host name. + InsecureSkipVerify bool `mapstructure:"insecure_skip_verify"` +} diff --git a/receiver/kubeletstatsreceiver/kubelet/client_test.go b/receiver/kubeletstatsreceiver/kubelet/client_test.go index 00f3f37724dc..a349ca0cc8b3 100644 --- a/receiver/kubeletstatsreceiver/kubelet/client_test.go +++ b/receiver/kubeletstatsreceiver/kubelet/client_test.go @@ -15,20 +15,28 @@ package kubelet import ( - "crypto/tls" "crypto/x509" + "errors" "io" "net/http" "strings" "testing" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/config/configtls" + "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/k8sconfig" ) +const certPath = "../testdata/testcert.crt" +const keyFile = "../testdata/testkey.key" +const tokenPath = "../testdata/token" + func TestClient(t *testing.T) { tr := &fakeRoundTripper{} baseURL := "http://localhost:9876" - client := &tlsClient{ + client := &clientImpl{ baseURL: baseURL, httpClient: http.Client{Transport: tr}, } @@ -43,44 +51,209 @@ func TestClient(t *testing.T) { require.Equal(t, "GET", tr.method) } +func TestNewClient(t *testing.T) { + client, err := NewClient("localhost:9876", &ClientConfig{ + APIConfig: k8sconfig.APIConfig{ + AuthType: k8sconfig.AuthTypeTLS, + }, + TLSSetting: configtls.TLSSetting{ + CAFile: certPath, + CertFile: certPath, + KeyFile: keyFile, + }, + }, zap.NewNop()) + require.NoError(t, err) + require.NotNil(t, client) + c := client.(*clientImpl) + tcc := c.httpClient.Transport.(*http.Transport).TLSClientConfig + require.Equal(t, 1, len(tcc.Certificates)) + require.NotNil(t, tcc.RootCAs) +} + func TestDefaultTLSClient(t *testing.T) { endpoint := "localhost:9876" - client := defaultTLSClient(endpoint, true, &x509.CertPool{}, tls.Certificate{}, nil) + client, err := defaultTLSClient(endpoint, true, &x509.CertPool{}, nil, nil, zap.NewNop()) + require.NoError(t, err) require.NotNil(t, client.httpClient.Transport) require.Equal(t, "https://"+endpoint, client.baseURL) } +func TestSvcAcctClient(t *testing.T) { + cl, err := newServiceAccountClient( + "localhost:9876", certPath, tokenPath, zap.NewNop(), + ) + require.NoError(t, err) + require.Equal(t, "s3cr3t", string(cl.tok)) +} + +func TestDefaultEndpoint(t *testing.T) { + endpt, err := defaultEndpoint() + require.NoError(t, err) + require.True(t, strings.HasSuffix(endpt, ":10250")) +} + +func TestBadAuthType(t *testing.T) { + _, err := NewClient("foo", &ClientConfig{ + APIConfig: k8sconfig.APIConfig{ + AuthType: "bar", + }, + }, zap.NewNop()) + require.Error(t, err) +} + +func TestTLSMissingCAFile(t *testing.T) { + _, err := newTLSClient("", &ClientConfig{}, zap.NewNop()) + require.Error(t, err) +} + +func TestTLSMissingCertFile(t *testing.T) { + _, err := newTLSClient("", &ClientConfig{ + TLSSetting: configtls.TLSSetting{ + CAFile: certPath, + }, + }, zap.NewNop()) + require.Error(t, err) +} + +func TestSABadCertPath(t *testing.T) { + _, err := newServiceAccountClient("foo", "bar", "baz", zap.NewNop()) + require.Error(t, err) +} + +func TestSABadTokenPath(t *testing.T) { + _, err := newServiceAccountClient("foo", certPath, "bar", zap.NewNop()) + require.Error(t, err) +} + +func TestTLSDefaultEndpoint(t *testing.T) { + client, err := defaultTLSClient("", true, nil, nil, nil, zap.NewNop()) + require.NoError(t, err) + require.True(t, strings.HasPrefix(client.baseURL, "https://")) + require.True(t, strings.HasSuffix(client.baseURL, ":10250")) +} + +func TestBuildReq(t *testing.T) { + cl, err := newServiceAccountClient( + "localhost:9876", certPath, tokenPath, zap.NewNop(), + ) + require.NoError(t, err) + req, err := cl.buildReq("/foo") + require.NoError(t, err) + require.NotNil(t, req) + require.Equal(t, req.Header["Authorization"][0], "bearer s3cr3t") +} + +func TestBuildBadReq(t *testing.T) { + cl, err := newServiceAccountClient( + "localhost:9876", certPath, tokenPath, zap.NewNop(), + ) + require.NoError(t, err) + _, err = cl.buildReq(" ") + require.Error(t, err) +} + +func TestFailedRT(t *testing.T) { + tr := &fakeRoundTripper{failOnRT: true} + baseURL := "http://localhost:9876" + client := &clientImpl{ + baseURL: baseURL, + httpClient: http.Client{Transport: tr}, + } + _, err := client.Get("/foo") + require.Error(t, err) +} + +func TestBadReq(t *testing.T) { + tr := &fakeRoundTripper{} + baseURL := "http://localhost:9876" + client := &clientImpl{ + baseURL: baseURL, + httpClient: http.Client{Transport: tr}, + } + _, err := client.Get(" ") + require.Error(t, err) +} + +func TestErrOnClose(t *testing.T) { + tr := &fakeRoundTripper{errOnClose: true} + baseURL := "http://localhost:9876" + client := &clientImpl{ + baseURL: baseURL, + httpClient: http.Client{Transport: tr}, + logger: zap.NewNop(), + } + resp, err := client.Get("/foo") + require.NoError(t, err) + require.NotNil(t, resp) +} + +func TestErrOnRead(t *testing.T) { + tr := &fakeRoundTripper{errOnRead: true} + baseURL := "http://localhost:9876" + client := &clientImpl{ + baseURL: baseURL, + httpClient: http.Client{Transport: tr}, + logger: zap.NewNop(), + } + resp, err := client.Get("/foo") + require.Error(t, err) + require.Nil(t, resp) +} + var _ http.RoundTripper = (*fakeRoundTripper)(nil) type fakeRoundTripper struct { - closed bool - header http.Header - method string - url string + closed bool + header http.Header + method string + url string + failOnRT bool + errOnClose bool + errOnRead bool } func (f *fakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + if f.failOnRT { + return nil, errors.New("failOnRT == true") + } f.header = req.Header f.method = req.Method f.url = req.URL.String() + var reader io.Reader + if f.errOnRead { + reader = &failingReader{} + } else { + reader = strings.NewReader("hello") + } return &http.Response{ Body: &fakeReadCloser{ - Reader: strings.NewReader("hello"), - onClose: func() { + Reader: reader, + onClose: func() error { f.closed = true + if f.errOnClose { + return errors.New("") + } + return nil }, }, }, nil } +var _ io.Reader = (*failingReader)(nil) + +type failingReader struct{} + +func (f *failingReader) Read([]byte) (n int, err error) { + return 0, errors.New("") +} + var _ io.ReadCloser = (*fakeReadCloser)(nil) type fakeReadCloser struct { io.Reader - onClose func() + onClose func() error } func (f *fakeReadCloser) Close() error { - f.onClose() - return nil + return f.onClose() } diff --git a/receiver/kubeletstatsreceiver/testdata/config.yaml b/receiver/kubeletstatsreceiver/testdata/config.yaml new file mode 100644 index 000000000000..59bf153a76ec --- /dev/null +++ b/receiver/kubeletstatsreceiver/testdata/config.yaml @@ -0,0 +1,20 @@ +receivers: + kubeletstats/tls: + collection_interval: 10s + auth_type: "tls" + ca_file: "/path/to/ca.crt" + key_file: "/path/to/apiserver.key" + cert_file: "/path/to/apiserver.crt" + endpoint: "1.2.3.4:5555" + insecure_skip_verify: true + kubeletstats/sa: + collection_interval: 10s + auth_type: "serviceAccount" + insecure_skip_verify: true +exporters: + exampleexporter: +service: + pipelines: + metrics: + receivers: [kubeletstats/sa] + exporters: [exampleexporter] diff --git a/receiver/kubeletstatsreceiver/testdata/testcert.crt b/receiver/kubeletstatsreceiver/testdata/testcert.crt new file mode 100644 index 000000000000..668c82145c67 --- /dev/null +++ b/receiver/kubeletstatsreceiver/testdata/testcert.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDLDCCAhSgAwIBAgIJAO8ClxUckM5xMA0GCSqGSIb3DQEBCwUAMEsxCzAJBgNV +BAYTAk9UMRYwFAYDVQQIDA1PcGVuVGVsZW1ldHJ5MRAwDgYDVQQHDAdTZXJ2aWNl +MRIwEAYDVQQDDAkxMjcuMC4wLjEwHhcNMjAwNTA2MDAzMTQ0WhcNMjEwNTA2MDAz +MTQ0WjBLMQswCQYDVQQGEwJPVDEWMBQGA1UECAwNT3BlblRlbGVtZXRyeTEQMA4G +A1UEBwwHU2VydmljZTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAyVL12RmIXJP/K1wkGDW2k9OKvmP/kX0w2iPEZ7f0 +3kUvDpAUjGHr3FnnOYYmxQU+gXK0g/pRupNh5n4GuzFGbQNEAl1V+dmAB5w/yX3p +SSZVZmsIRRgTVRd1501mDNqRS6aOy8+PhFUF7rI6V5KBaizLch6ojOtDSouUTnRI +9o47WSeyVALHFllm1BYlCBoiSZ/ZX2BJOteJ/9fawPQzVMSmNOQcymRiHqeBlhlI +gIPFEOh68oJScGNRVin0tnxfUr7eO+cR3iC20aCUXsL3Yq1KKXrxD3/0T8ICK5DM +qWj4gKC4CVlIF68zvVWD/jKSR9u9Gs+aRxA2ZHF+scsHgQIDAQABoxMwETAPBgNV +HREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQA2DT7VxpFLCqc0FHW16yZ9 +/9fQChEN5IBe6mjbysjeYhef8w7xP03wl6SwFXFpTQDFqz6KdolH+Zl4gm6MsrsX +nQNP8fkHfNtHr+28JPDPWC5aWx5xfdQ4ybfeEV+xdNmrKeKGOcQ+Nmjcx06ysy0J +OSjOBwyTvlCIOF5AnafFuCk81EnbMLQeIvsfudXTAi0aw6HMmS2UgmGUcwGsFDRt +Xx1n1nLclK73f2a9mrzrh1s3lMom1FLaZ8fRecB9cVZJAHdw7RDtkG0qFf+v9Hk0 +y8JKVfSmRIveHz62a/61T36VSKIO0qksdR4wEPCjADsdpagVMrwjyu8qShLFXRkn +-----END CERTIFICATE----- diff --git a/receiver/kubeletstatsreceiver/testdata/testkey.key b/receiver/kubeletstatsreceiver/testdata/testkey.key new file mode 100644 index 000000000000..b83561755f08 --- /dev/null +++ b/receiver/kubeletstatsreceiver/testdata/testkey.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyVL12RmIXJP/K1wkGDW2k9OKvmP/kX0w2iPEZ7f03kUvDpAU +jGHr3FnnOYYmxQU+gXK0g/pRupNh5n4GuzFGbQNEAl1V+dmAB5w/yX3pSSZVZmsI +RRgTVRd1501mDNqRS6aOy8+PhFUF7rI6V5KBaizLch6ojOtDSouUTnRI9o47WSey +VALHFllm1BYlCBoiSZ/ZX2BJOteJ/9fawPQzVMSmNOQcymRiHqeBlhlIgIPFEOh6 +8oJScGNRVin0tnxfUr7eO+cR3iC20aCUXsL3Yq1KKXrxD3/0T8ICK5DMqWj4gKC4 +CVlIF68zvVWD/jKSR9u9Gs+aRxA2ZHF+scsHgQIDAQABAoIBAG/6OMw8K2By4ObZ +JSpiFd87NlyXejsOCvIKGuAlrYlDqdzLvuImRO4XA0k3mLDVLeMKTeVqgbLo7vco ++c18ptNTkaxPBdcmZtPU0JXd9re9HpsMxVjI/1fA6M9yeWSE3XPafGpYVFcig140 +u8ahsmG/8JjU/KME6DS6Vg8dFsgrb0aJypv1VxA2n4xeWkbwVdniTlny4LFhwvvk +P4dgnGNhUHkeet+re9YZEkXJbNp9hXP/wdEwLJ5tUNI/exngxQaAJ6fP2e1htFoJ +a8TGTwjEwRIAocjI8ieHnUO4lARF8uhEzhSadtZNZvKgbNpE5xJNl9OH9pkQTjo2 +4CLOxpECgYEA8ZbV2o1EcdCKvIWAYhYbBHYe2gadcnO04gtA1bbGk/+YtzaiS20W +zq2qKDhrQJ6sCFe17CN9hM0gdkpsyS1nLtR3F3MVacYe8STh7BD61E5ens+wDWJU +zva3bS1CRMPthZ+i0xc4AOgXDZewD1rxb8rvT5SeXYRZGkvyh9TAzocCgYEA1VVC +lLy3EG/geiMAWd+FnTwWnMViGb8rDY03vJDSKEes9b8HqwEPsX0I3TVeyyYBM3Te +sPYqJxBFh5afU8DYhNue9UbJKSN4j1jg43pK58i99LT+lGRAVaJZLVbsWiEF3MwX +8muCtELAT7j9648oEUX4sF/nnz422Q0VPRS5s7cCgYAqrDHqALnuQJ/A3PPoX282 +QocAi9qTtMxmgQZauYYp7iPTeNsB56r3psU/hXesWlqYvqVrqHkrU/A/9LVyc4qe +QvkmMzW9ETm17oXZZMZpac5czuKR+qRwSjPsHOpvqwvxZlkkYB2MS3KG/BwlGjM7 +Q+UxcVbnvdDfTDrysym7UQKBgQDFeVPVjM7EZ1tak7XKe68aOjoQSmIhxSTcOYGD +imcPJDIFlRxK/gOB32TqJ3IlCHwKHr/Y/TVNzbEe7p1zkMqcSRPepfSloREDWFls +GJLn9ZlowHX79MTcwBhecNz+HR1pIn90RnLJ3BRad7qMZ4rGWof28//bF2L8DjE/ +xkSUBwKBgQCAki3+tscHa1ZQ+VZmvTeQ9gwNZt+cm0FzavhjnvWZAKCrKwg+MvAN +BifZjKsPK7u9u1QGuPP0Zn/Zw3VoMlrC/Paa/OZzwTtb2yN824wbMo0Qvm5WciS7 +DXyNy887h1NLGEyMh6rGUutmI6OPf8WaLqcxrz16dhtr9+N6YDZ/tQ== +-----END RSA PRIVATE KEY----- diff --git a/receiver/kubeletstatsreceiver/testdata/token b/receiver/kubeletstatsreceiver/testdata/token new file mode 100644 index 000000000000..81d66969d3c5 --- /dev/null +++ b/receiver/kubeletstatsreceiver/testdata/token @@ -0,0 +1 @@ +s3cr3t \ No newline at end of file