Skip to content

Commit 18340f4

Browse files
authored
Update pxapi Go client to enforce an opt in mechanism when TLS is disabled (#1746)
Summary: Update pxapi Go client to enforce an opt in mechanism when TLS is disabled Disabling TLS is often useful for test environments, but is not expected to be relied on in any non test environments. The doc string of NewClient was updated, so that this new behavior will explained in the pxapi's [Godoc documentation](https://pkg.go.dev/px.dev/pxapi#NewClient). Relevant Issues: N/A Type of change: /kind bug Test Plan: The following scenarios were tested to ensure the opt in mechanism is functional 1. Verified that the default behavior does not disable TLS <details> <summary>output</summary> ``` # Set cloud.cluster.local to the IP address of work.withpixie.ai $ grep cloud /etc/hosts 34.102.151.106 cloud.cluster.local # Set cloud address to a cluster.local domain $ git diff diff --git a/src/api/go/pxapi/examples/basic_example/example.go b/src/api/go/pxapi/examples/basic_example/example.go index 16e71f9..cea9fd9ee0 100644 --- a/src/api/go/pxapi/examples/basic_example/example.go +++ b/src/api/go/pxapi/examples/basic_example/example.go @@ -74,7 +74,9 @@ func main() { } ctx := context.Background() - client, err := pxapi.NewClient(ctx, pxapi.WithAPIKey(apiKey)) + cloudAddr := "cloud.cluster.local:443" + // client, err := pxapi.NewClient(ctx, pxapi.WithAPIKey(apiKey)) + client, err := pxapi.NewClient(ctx, pxapi.WithAPIKey(apiKey), pxapi.WithCloudAddr(cloudAddr)) if err != nil { panic(err) } $ PX_CLUSTER_ID='<cluster id -- not secret>' PX_API_KEY=$(cat .px-api-key) bazel run src/api/go/pxapi/examples/basic_example:basic_example INFO: Invocation ID: a7111f36-8a12-45a7-a8f4-b28eab9c841c INFO: Streaming build results to: https://bb.corp.pixielabs.ai/invocation/a7111f36-8a12-45a7-a8f4-b28eab9c841c INFO: Analyzed target //src/api/go/pxapi/examples/basic_example:basic_example (0 packages loaded, 0 targets configured). INFO: Found 1 target... Target //src/api/go/pxapi/examples/basic_example:basic_example up-to-date: bazel-bin/src/api/go/pxapi/examples/basic_example/basic_example_/basic_example INFO: Elapsed time: 0.367s, Critical Path: 0.02s INFO: 1 process: 1 internal. INFO: Running command line: bazel-bin/src/api/go/pxapi/examples/basic_example/basic_example_/basic_example INFO: Streaming build results to: https://bb.corp.pixielabs.ai/invocation/a7111f36-8a12-45a7-a8f4-b28eab9c841c INFO: Build completed successfully, 1 total action Running on Cluster: fbef7892-6302-4bd4-8b55-ae2a93d556fc Running script panic: rpc error: code = Unavailable desc = connection error: desc = "transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate is valid for withpixie.ai, work.withpixie.ai, docs.withpixie.ai, segment.withpixie.ai, not cloud.cluster.local" goroutine 1 [running]: main.main() src/api/go/pxapi/examples/basic_example/example.go:95 +0x498 ``` </details> 2. Verified that if the cloud hostname is overridden, that TLS will not be disabled if `PX_DISABLE_TLS` is not set to `1` <details> <summary>output</summary> ``` # The following change was applied to main in order to test this and the next scenario $ git diff diff --git a/src/api/go/pxapi/examples/basic_example/example.go b/src/api/go/pxapi/examples/basic_example/example.go index 16e71f9..766ea39de0 100644 --- a/src/api/go/pxapi/examples/basic_example/example.go +++ b/src/api/go/pxapi/examples/basic_example/example.go @@ -74,7 +74,9 @@ func main() { } ctx := context.Background() - client, err := pxapi.NewClient(ctx, pxapi.WithAPIKey(apiKey)) + cloudAddr := "cloud.cluster.local:443" + // client, err := pxapi.NewClient(ctx, pxapi.WithAPIKey(apiKey)) + client, err := pxapi.NewClient(ctx, pxapi.WithAPIKey(apiKey), pxapi.WithCloudAddr(cloudAddr), pxapi.WithDisableTLSVerification(cloudAddr)) $ PX_CLUSTER_ID='<cluster id -- not secret>' PX_API_KEY=$(cat .px-api-key) bazel run src/api/go/pxapi/examples/basic_example:basic_example INFO: Invocation ID: a7111f36-8a12-45a7-a8f4-b28eab9c841c INFO: Streaming build results to: https://bb.corp.pixielabs.ai/invocation/a7111f36-8a12-45a7-a8f4-b28eab9c841c INFO: Analyzed target //src/api/go/pxapi/examples/basic_example:basic_example (0 packages loaded, 0 targets configured). INFO: Found 1 target... Target //src/api/go/pxapi/examples/basic_example:basic_example up-to-date: bazel-bin/src/api/go/pxapi/examples/basic_example/basic_example_/basic_example INFO: Elapsed time: 0.367s, Critical Path: 0.02s INFO: 1 process: 1 internal. INFO: Running command line: bazel-bin/src/api/go/pxapi/examples/basic_example/basic_example_/basic_example INFO: Streaming build results to: https://bb.corp.pixielabs.ai/invocation/a7111f36-8a12-45a7-a8f4-b28eab9c841c INFO: Build completed successfully, 1 total action 2023/11/02 18:23:15 The `PX_DISABLE_TLS` environment variable must be set to "1" when making cloud connections that do not support TLS. ``` </details> 3. Verified that if the cloud hostname is overridden and `PX_DISABLE_TLS=1` that TLS will be disabled. <details> <summary>output</summary> ``` $ PX_DISABLE_TLS=1 PX_CLUSTER_ID='<cluster id -- not secret>' PX_API_KEY=$(cat .px-api-key) bazel run src/api/go/pxapi/examples/basic_example:basic_example INFO: Invocation ID: 18efc480-2caf-4598-886e-7a1a5ac15fd9 INFO: Streaming build results to: https://bb.corp.pixielabs.ai/invocation/18efc480-2caf-4598-886e-7a1a5ac15fd9 INFO: Analyzed target //src/api/go/pxapi/examples/basic_example:basic_example (0 packages loaded, 0 targets configured). INFO: Found 1 target... Target //src/api/go/pxapi/examples/basic_example:basic_example up-to-date: bazel-bin/src/api/go/pxapi/examples/basic_example/basic_example_/basic_example INFO: Elapsed time: 0.287s, Critical Path: 0.02s INFO: 1 process: 1 internal. INFO: Running command line: bazel-bin/src/api/go/pxapi/examples/basic_example/basic_example_/basic_example INFO: Streaming build results to: https://bb.corp.pixielabs.ai/invocation/18efc480-2caf-4598-886e-7a1a5ac15fd9 INFO: Build completed successfully, 1 total action Running on Cluster: fbef7892-6302-4bd4-8b55-ae2a93d556fc Running on Cluster: fbef7892-6302-4bd4-8b55-ae2a93d556fc Running script 000008bf-0000-0aa8-0000-000000000742 /healthz 169.254.169.254 GET 000008bf-0000-0eff-0000-000000000a1b /readyz 10.68.192.129 GET 000008bf-0000-0eff-0000-000000000a1b /healthz 10.68.192.129 GET 000008bf-0000-0f06-0000-000000000a1b /healthz 10.68.192.129 GET 000008bf-0000-0f06-0000-000000000a1b /readyz 10.68.192.129 GET 000008bf-0000-0fb4-0000-000000000ae3 /readiness 10.68.192.129 GET 000008bf-0000-1113-0000-000000000d0a /healthcheck/dnsmasq 10.68.192.129 GET 000008bf-0000-1113-0000-000000000d0a /healthcheck/kubedns 10.68.192.129 GET 000008bf-0000-1113-0000-000000000d0a /metrics 10.68.192.129 GET 000008bf-0006-b357-0000-000003ab11bd /is-dynamic-lb-initialized 127.0.0.1 GET Execution Time: 940µs Bytes received: 646 ``` </details> --------- Signed-off-by: Dom Del Nano <ddelnano@pixielabs.ai>
1 parent 05fb849 commit 18340f4

File tree

4 files changed

+85
-6
lines changed

4 files changed

+85
-6
lines changed

src/api/go/pxapi/BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ filegroup(
5858

5959
pl_go_test(
6060
name = "pxapi_test",
61-
srcs = ["results_test.go"],
61+
srcs = [
62+
"opts_test.go",
63+
"results_test.go",
64+
],
6265
embed = [":pxapi"],
6366
deps = [
6467
"//src/api/go/pxapi/errdefs",

src/api/go/pxapi/client.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"context"
2323
"crypto/tls"
2424
"fmt"
25-
"strings"
2625

2726
"google.golang.org/grpc"
2827
"google.golang.org/grpc/credentials"
@@ -61,7 +60,8 @@ type Client struct {
6160

6261
cloudAddr string
6362

64-
useEncryption bool
63+
useEncryption bool
64+
disableTLSVerification bool
6565

6666
grpcConn *grpc.ClientConn
6767
cmClient cloudpb.VizierClusterInfoClient
@@ -86,9 +86,7 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) {
8686
}
8787

8888
func (c *Client) init(ctx context.Context) error {
89-
isInternal := strings.Contains(c.cloudAddr, "cluster.local")
90-
91-
tlsConfig := &tls.Config{InsecureSkipVerify: isInternal}
89+
tlsConfig := &tls.Config{InsecureSkipVerify: c.disableTLSVerification}
9290
creds := credentials.NewTLS(tlsConfig)
9391

9492
conn, err := grpc.Dial(c.cloudAddr, grpc.WithTransportCredentials(creds))

src/api/go/pxapi/opts.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818

1919
package pxapi
2020

21+
import (
22+
"log"
23+
"os"
24+
"strings"
25+
)
26+
2127
// ClientOption configures options on the client.
2228
type ClientOption func(client *Client)
2329

@@ -28,6 +34,21 @@ func WithCloudAddr(cloudAddr string) ClientOption {
2834
}
2935
}
3036

37+
// Allows disabling TLS verification if the `PX_DISABLE_TLS` env var is set and the cloud address is a cluster domain (cluster.local).
38+
func WithDisableTLSVerification(cloudAddr string) ClientOption {
39+
return func(c *Client) {
40+
isInternal := strings.Contains(cloudAddr, "cluster.local")
41+
tlsDisabled := os.Getenv("PX_DISABLE_TLS") == "1"
42+
insecureSkipVerify := tlsDisabled && isInternal
43+
44+
if !tlsDisabled && isInternal {
45+
log.Fatalf("The `PX_DISABLE_TLS` environment variable must be set to \"1\" when making cloud connections that do not support TLS.\n")
46+
} else {
47+
c.disableTLSVerification = insecureSkipVerify
48+
}
49+
}
50+
}
51+
3152
// WithBearerAuth is the option to specify bearer auth to use.
3253
func WithBearerAuth(auth string) ClientOption {
3354
return func(c *Client) {

src/api/go/pxapi/opts_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2018- The Pixie Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
*/
18+
19+
package pxapi
20+
21+
import (
22+
"os"
23+
"testing"
24+
25+
"github.com/stretchr/testify/assert"
26+
)
27+
28+
func TestWithDisableTLSVerificationOnlyAppliesForLocalConn(t *testing.T) {
29+
if err := os.Setenv("PX_DISABLE_TLS", "1"); err != nil {
30+
t.Fatalf("failed to set the `PX_DISABLE_TLS` environment variable: %v", err)
31+
}
32+
c := &Client{}
33+
// Hostname that isn't a cluster domain (cluster.local or custom domain)
34+
opt := WithDisableTLSVerification("work.withpixie.ai")
35+
opt(c)
36+
37+
assert.False(t, c.disableTLSVerification)
38+
39+
if err := os.Unsetenv("PX_DISABLE_TLS"); err != nil {
40+
t.Fatalf("failed to unset the `PX_DISABLE_TLS` environment variable: %v", err)
41+
}
42+
}
43+
44+
func TestWithDisableTLSVerificationWithEnvVarSet(t *testing.T) {
45+
if err := os.Setenv("PX_DISABLE_TLS", "1"); err != nil {
46+
t.Fatalf("failed to set the `PX_DISABLE_TLS` environment variable: %v", err)
47+
}
48+
c := &Client{}
49+
opt := WithDisableTLSVerification("cluster.local")
50+
opt(c)
51+
52+
assert.True(t, c.disableTLSVerification)
53+
54+
if err := os.Unsetenv("PX_DISABLE_TLS"); err != nil {
55+
t.Fatalf("failed to unset the `PX_DISABLE_TLS` environment variable: %v", err)
56+
}
57+
}

0 commit comments

Comments
 (0)