From d181d53ebe9ba3fe10660b08162b49bcd4041dd2 Mon Sep 17 00:00:00 2001 From: Kajetan Date: Thu, 14 Nov 2024 22:49:58 +0100 Subject: [PATCH 1/3] Support TLS without certifactes --- .github/workflows/linux.yml | 12 +++++ config.go | 24 ++++++---- tests/configs/.rr-h2c.yaml | 19 ++++++++ tests/env/docker-compose-temporal.yaml | 12 ++++- tests/env/h2c.yaml | 63 ++++++++++++++++++++++++++ tests/general/h2c_test.go | 52 +++++++++++++++++++++ 6 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 tests/configs/.rr-h2c.yaml create mode 100644 tests/env/h2c.yaml create mode 100644 tests/general/h2c_test.go diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 94c9518..b867263 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -134,6 +134,18 @@ jobs: run: | mkdir ./tests/coverage-ci + - name: Add custom CA certificate + run: | + cd tests + + ./env/temporal_tls/generate-test-certs.sh + export TEMPORAL_TLS_CERTS_DIR=/etc/temporal/config/certs + export TEMPORAL_LOCAL_CERT_DIR=$(pwd)/env/temporal_tls/certs + + sudo cp $(pwd)/env/temporal_tls/certs/ca.cert /usr/local/share/ca-certificates/ca.crt + + sudo update-ca-certificates + - name: Run Temporal canceller module tests run: | go test -timeout 20m -v -race -cover -tags=debug -failfast -coverpkg=$(cat ./tests/pkgs.txt) -coverprofile=./tests/coverage-ci/rrt_c.out -covermode=atomic canceller/canceller.go canceller/canceller_test.go diff --git a/config.go b/config.go index 057bc79..f0c3194 100644 --- a/config.go +++ b/config.go @@ -138,20 +138,24 @@ func (c *Config) InitDefault() error { } if c.TLS != nil { - if _, err := os.Stat(c.TLS.Key); err != nil { - if os.IsNotExist(err) { - return errors.E(op, errors.Errorf("private key file '%s' does not exist", c.TLS.Key)) - } + if c.TLS.Key != "" { + if _, err := os.Stat(c.TLS.Key); err != nil { + if os.IsNotExist(err) { + return errors.E(op, errors.Errorf("private key file '%s' does not exist", c.TLS.Key)) + } - return errors.E(op, err) + return errors.E(op, err) + } } - if _, err := os.Stat(c.TLS.Cert); err != nil { - if os.IsNotExist(err) { - return errors.E(op, errors.Errorf("public certificate file '%s' does not exist", c.TLS.Cert)) - } + if c.TLS.Cert != "" { + if _, err := os.Stat(c.TLS.Cert); err != nil { + if os.IsNotExist(err) { + return errors.E(op, errors.Errorf("public certificate file '%s' does not exist", c.TLS.Cert)) + } - return errors.E(op, err) + return errors.E(op, err) + } } // RootCA is optional, but if provided - check it diff --git a/tests/configs/.rr-h2c.yaml b/tests/configs/.rr-h2c.yaml new file mode 100644 index 0000000..13246e6 --- /dev/null +++ b/tests/configs/.rr-h2c.yaml @@ -0,0 +1,19 @@ +version: '3' + +rpc: + listen: tcp://127.0.0.1:6001 + +server: + command: "php ../php_test_files/worker.php" + +temporal: + address: "127.0.0.1:4433" + cache_size: 10 + activities: + num_workers: 1 + tls: + client_auth_type: no_client_certs + +logs: + mode: development + level: debug diff --git a/tests/env/docker-compose-temporal.yaml b/tests/env/docker-compose-temporal.yaml index 9802a46..0b41060 100644 --- a/tests/env/docker-compose-temporal.yaml +++ b/tests/env/docker-compose-temporal.yaml @@ -12,14 +12,22 @@ services: - "8125:8125/udp" - "8126:8126" + envoy: + image: bitnami/envoy:latest + ports: + - "4433:443" + volumes: + - ./h2c.yaml:/opt/bitnami/envoy/conf/envoy.yaml + - ./temporal_tls/certs/client.pem:/etc/envoy/client.pem + - ./temporal_tls/certs/client.key:/etc/envoy/client.key + - ./temporal_tls/certs/ca.cert:/etc/envoy/ca.cert + postgresql: container_name: temporal-postgresql image: postgres:latest environment: POSTGRES_PASSWORD: temporal POSTGRES_USER: temporal - ports: - - "5432:5432" temporal-ui: container_name: temporal-ui diff --git a/tests/env/h2c.yaml b/tests/env/h2c.yaml new file mode 100644 index 0000000..a19f58f --- /dev/null +++ b/tests/env/h2c.yaml @@ -0,0 +1,63 @@ +static_resources: + listeners: + - name: listener_0 + address: + socket_address: + address: 0.0.0.0 + port_value: 443 # Public-facing TLS port + filter_chains: + - filter_chain_match: {} + filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + codec_type: AUTO + route_config: + name: local_route + virtual_hosts: + - name: grpc_service + domains: + - "*" # Allows all domains to access + routes: + - match: + prefix: "/" + route: + cluster: grpc_backend + timeout: 0s + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + upgrade_configs: + - upgrade_type: h2c # Enables h2c upgrade for cleartext HTTP/2 + transport_socket: # Move this out to align with filter_chains + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + alpn_protocols: "h2" + tls_certificates: + - certificate_chain: + filename: "/etc/envoy/client.pem" + private_key: + filename: "/etc/envoy/client.key" + validation_context: + trusted_ca: + filename: "/etc/envoy/ca.cert" + + clusters: + - name: grpc_backend + connect_timeout: 5s + type: LOGICAL_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: grpc_backend + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: temporal # Temporal service hostname + port_value: 7233 # Temporal service port + http2_protocol_options: {} # Enables HTTP/2 for cleartext h2c communication diff --git a/tests/general/h2c_test.go b/tests/general/h2c_test.go new file mode 100644 index 0000000..b6cd041 --- /dev/null +++ b/tests/general/h2c_test.go @@ -0,0 +1,52 @@ +package tests + +import ( + "context" + "sync" + "testing" + "time" + + "tests/helpers" + + "github.com/stretchr/testify/assert" + "go.temporal.io/sdk/client" +) + +func Test_H2CWithoutCerts(t *testing.T) { + stopCh := make(chan struct{}, 1) + wg := &sync.WaitGroup{} + wg.Add(1) + s := helpers.NewTestServer(t, stopCh, wg, "../configs/.rr-h2c.yaml") + + w, err := s.Client.ExecuteWorkflow( + context.Background(), + client.StartWorkflowOptions{ + TaskQueue: "default", + }, + "HistoryLengthWorkflow") + assert.NoError(t, err) + + time.Sleep(time.Second) + var result any + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + assert.NoError(t, w.Get(ctx, &result)) + + res := []float64{3, 8, 8, 15} + out := result.([]interface{}) + + for i := 0; i < len(res); i++ { + if res[i] != out[i].(float64) { + t.Fail() + } + } + + we, err := s.Client.DescribeWorkflowExecution(context.Background(), w.GetID(), w.GetRunID()) + assert.NoError(t, err) + + assert.Equal(t, "Completed", we.WorkflowExecutionInfo.Status.String()) + stopCh <- struct{}{} + wg.Wait() + time.Sleep(time.Second) +} From b19a16f008952c0768e0cefc22d8ceac938ee3cd Mon Sep 17 00:00:00 2001 From: Kajetan Date: Fri, 15 Nov 2024 14:37:10 +0100 Subject: [PATCH 2/3] Support TLS without certifactes --- tls.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tls.go b/tls.go index 4bfa57f..b1143c1 100644 --- a/tls.go +++ b/tls.go @@ -43,9 +43,8 @@ func initTLS(cfg *Config) (*tls.Config, error) { } return &tls.Config{ - ServerName: cfg.TLS.ServerName, - MinVersion: tls.VersionTLS12, - GetClientCertificate: getClientCertificate(cfg), + ServerName: cfg.TLS.ServerName, + MinVersion: tls.VersionTLS12, }, nil } From 8a838fa15bba57c34b7e7baf89f6a8e56d88933e Mon Sep 17 00:00:00 2001 From: Kajetan Date: Fri, 15 Nov 2024 17:07:12 +0100 Subject: [PATCH 3/3] Support TLS without certifactes --- config.go | 1 + tests/configs/.rr-h2c.yaml | 4 ++-- tls.go | 12 ++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/config.go b/config.go index f0c3194..ec3fa72 100644 --- a/config.go +++ b/config.go @@ -85,6 +85,7 @@ type TLS struct { RootCA string `mapstructure:"root_ca"` AuthType ClientAuthType `mapstructure:"client_auth_type"` ServerName string `mapstructure:"server_name"` + UseH2C bool `mapstructure:"use_h2c"` // auth type auth tls.ClientAuthType } diff --git a/tests/configs/.rr-h2c.yaml b/tests/configs/.rr-h2c.yaml index 13246e6..f8a487b 100644 --- a/tests/configs/.rr-h2c.yaml +++ b/tests/configs/.rr-h2c.yaml @@ -7,12 +7,12 @@ server: command: "php ../php_test_files/worker.php" temporal: - address: "127.0.0.1:4433" + address: "localhost:4433" cache_size: 10 activities: num_workers: 1 tls: - client_auth_type: no_client_certs + use_h2c: true logs: mode: development diff --git a/tls.go b/tls.go index b1143c1..7d9becf 100644 --- a/tls.go +++ b/tls.go @@ -42,9 +42,17 @@ func initTLS(cfg *Config) (*tls.Config, error) { }, nil } + if cfg.TLS.UseH2C { + return &tls.Config{ + ServerName: cfg.TLS.ServerName, + MinVersion: tls.VersionTLS12, + }, nil + } + return &tls.Config{ - ServerName: cfg.TLS.ServerName, - MinVersion: tls.VersionTLS12, + ServerName: cfg.TLS.ServerName, + GetClientCertificate: getClientCertificate(cfg), + MinVersion: tls.VersionTLS12, }, nil }