From f67043a76e579fb9d217c82d924857f0d807cb05 Mon Sep 17 00:00:00 2001 From: Brendan Myers Date: Wed, 9 Jul 2025 22:03:26 +1000 Subject: [PATCH 1/3] feat: api key auth + config reorg --- cmd/main.go | 13 +- config.yaml.sample | 37 +++-- proxy/proxy.go | 87 +++++++---- proxy/proxy_test.go | 163 ++++++++++++++------ utils/config.go | 21 ++- utils/config_test.go | 360 +++++++++++++++++++++++++++++++++++-------- 6 files changed, 512 insertions(+), 169 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index dce4589..3205819 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -149,9 +149,9 @@ func configureProxy(proxyConns *proxy.Conn, cfg *utils.Config) error { metricsHandler := metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{ // Todo: do we need these many attributes? InitialAttributes: attribute.NewSet( - attribute.String("proxy-id", t.ProxyId), - attribute.String("target", t.Target), - attribute.String("namespace", t.Namespace), + attribute.String("proxy_id", t.ProxyId), + attribute.String("namespace", t.TemporalCloud.Namespace), + attribute.String("host_port", t.TemporalCloud.HostPort), attribute.String("auth_type", authType), attribute.String("encryption_key", t.EncryptionKey), ), @@ -172,12 +172,7 @@ func configureProxy(proxyConns *proxy.Conn, cfg *utils.Config) error { } err := proxyConns.AddConn(proxy.AddConnInput{ - ProxyId: t.ProxyId, - Target: t.Target, - TLSCertPath: t.TLS.CertFile, - TLSKeyPath: t.TLS.KeyFile, - EncryptionKeyID: t.EncryptionKey, - Namespace: t.Namespace, + Target: &t, AuthManager: authManager, AuthType: authType, MetricsHandler: metricsHandler, diff --git a/config.yaml.sample b/config.yaml.sample index 542a687..6c60903 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -1,21 +1,29 @@ server: port: 7233 host: "0.0.0.0" + metrics: port: 9090 + encryption: caching: max_cache: 100 max_age: "10m" max_usage: 100 + targets: - - source: "..internal" - target: "..tmprl.cloud:7233" - tls: - cert_file: "/path/to/./tls.crt" - key_file: "/path/to/./tls.key" + - proxy_id: "..internal" + temporal_cloud: + namespace: "." + host_port: "..tmprl.cloud:7233" # endpoint when using mTLS + # host_port: "..api.temporal.io:7233" # endpoint when using API keys + authentication: + # only set either tls or api_key + tls: + cert_file: "/path/to/./tls.crt" + key_file: "/path/to/./tls.key" + api_key: "" encryption_key: "" - namespace: "." authentication: type: "spiffe" config: @@ -24,13 +32,18 @@ targets: audiences: - "temporal_cloud_proxy" - - source: "..internal" - target: "..tmprl.cloud:7233" - tls: - cert_file: "/path/to/./tls.crt" - key_file: "/path/to/./tls.key" + - proxy_id: "..internal" + temporal_cloud: + namespace: "." + host_port: "..tmprl.cloud:7233" # endpoint when using mTLS + # host_port: "..api.temporal.io:7233" # endpoint when using API keys + authentication: + # only set either tls or api_key + tls: + cert_file: "/path/to/./tls.crt" + key_file: "/path/to/./tls.key" + api_key: "ey..." encryption_key: "" - namespace: "." authentication: type: "spiffe" config: diff --git a/proxy/proxy.go b/proxy/proxy.go index 3b0fd13..add6df0 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -5,24 +5,22 @@ import ( "crypto/tls" "errors" "fmt" - "go.temporal.io/sdk/converter" - "os" - "sync" - "temporal-sa/temporal-cloud-proxy/codec" - "temporal-sa/temporal-cloud-proxy/crypto" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/kms" - - "temporal-sa/temporal-cloud-proxy/auth" - "temporal-sa/temporal-cloud-proxy/metrics" - + "go.temporal.io/sdk/converter" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "os" + "sync" + "temporal-sa/temporal-cloud-proxy/auth" + "temporal-sa/temporal-cloud-proxy/codec" + "temporal-sa/temporal-cloud-proxy/crypto" + "temporal-sa/temporal-cloud-proxy/metrics" + "temporal-sa/temporal-cloud-proxy/utils" ) type Conn struct { @@ -59,12 +57,7 @@ func createKMSClient() *kms.KMS { // AddConnInput contains parameters for adding a new connection type AddConnInput struct { - ProxyId string - Target string - TLSCertPath string - TLSKeyPath string - EncryptionKeyID string - Namespace string + Target *utils.TargetConfig AuthManager *auth.AuthManager AuthType string MetricsHandler metrics.MetricsHandler @@ -73,18 +66,19 @@ type AddConnInput struct { // AddConn adds a new connection to the proxy func (mc *Conn) AddConn(input AddConnInput) error { - fmt.Printf("Adding connection id: %s target: %s\n", input.ProxyId, input.Target) + fmt.Printf("Adding connection id: %s namespace: %s hostport: %s\n", + input.Target.ProxyId, input.Target.TemporalCloud.Namespace, input.Target.TemporalCloud.HostPort) - cert, err := tls.LoadX509KeyPair(input.TLSCertPath, input.TLSKeyPath) - if err != nil { - return err + if input.Target.TemporalCloud.Authentication.ApiKey != "" && input.Target.TemporalCloud.Authentication.TLS != nil { + return fmt.Errorf("%s: cannot have both api key and mtls authentication configured on a single target", + input.Target.ProxyId) } //Initialize AWS KMS client kmsClient := createKMSClient() codecContext := map[string]string{ - "namespace": input.Namespace, + "namespace": input.Target.TemporalCloud.Namespace, } clientInterceptor, err := converter.NewPayloadCodecGRPCClientInterceptor( @@ -92,7 +86,7 @@ func (mc *Conn) AddConn(input AddConnInput) error { Codecs: []converter.PayloadCodec{codec.NewEncryptionCodecWithCaching( kmsClient, codecContext, - input.EncryptionKeyID, + input.Target.EncryptionKey, input.MetricsHandler, input.CryptoCachingConfig, )}, @@ -102,21 +96,52 @@ func (mc *Conn) AddConn(input AddConnInput) error { return err } + tlsConfig := tls.Config{} + + grpcInterceptors := []grpc.UnaryClientInterceptor{ + clientInterceptor, + } + + if input.Target.TemporalCloud.Authentication.ApiKey != "" { + grpcInterceptors = append(grpcInterceptors, + func(ctx context.Context, method string, req any, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + md, ok := metadata.FromIncomingContext(ctx) + + if ok { + md = md.Copy() + md.Delete("authorization") + md.Delete("temporal-namespace") + + ctx = metadata.NewOutgoingContext(ctx, md) + ctx = metadata.AppendToOutgoingContext(ctx, "temporal-namespace", input.Target.TemporalCloud.Namespace) + ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+input.Target.TemporalCloud.Authentication.ApiKey) + } + + return invoker(ctx, method, req, reply, cc, opts...) + }) + } else { + cert, err := tls.LoadX509KeyPair(input.Target.TemporalCloud.Authentication.TLS.CertFile, + input.Target.TemporalCloud.Authentication.TLS.KeyFile) + if err != nil { + return err + } + + tlsConfig.Certificates = []tls.Certificate{cert} + } + conn, err := grpc.NewClient( - input.Target, + input.Target.TemporalCloud.HostPort, grpc.WithTransportCredentials(credentials.NewTLS( - &tls.Config{ - Certificates: []tls.Certificate{cert}, - }, + &tlsConfig, )), - grpc.WithUnaryInterceptor(clientInterceptor), + grpc.WithChainUnaryInterceptor(grpcInterceptors...), ) if err != nil { return err } mc.mu.Lock() - mc.namespace[input.ProxyId] = NamespaceConn{ + mc.namespace[input.Target.ProxyId] = NamespaceConn{ conn: conn, authManager: input.AuthManager, authType: input.AuthType, @@ -137,8 +162,10 @@ func (mc *Conn) CloseAll() error { if err := namespace.conn.Close(); err != nil { errs = append(errs, err) } - if err := namespace.authManager.Close(); err != nil { - errs = append(errs, err) + if namespace.authManager != nil { + if err := namespace.authManager.Close(); err != nil { + errs = append(errs, err) + } } } diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 5f96621..1b89a20 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -17,6 +17,8 @@ import ( "time" "temporal-sa/temporal-cloud-proxy/auth" + "temporal-sa/temporal-cloud-proxy/metrics" + "temporal-sa/temporal-cloud-proxy/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -116,60 +118,123 @@ func TestConn_AddConn(t *testing.T) { errorMsg string }{ { - name: "successful connection addition", + name: "successful connection addition with TLS", input: AddConnInput{ - ProxyId: "test-proxy-id", - Target: "localhost:7233", - TLSCertPath: certPath, - TLSKeyPath: keyPath, - EncryptionKeyID: "test-key-id", - Namespace: "test-namespace", - AuthManager: nil, // Use nil for simplicity in tests - AuthType: "jwt", + Target: &utils.TargetConfig{ + ProxyId: "test-proxy-id", + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + TLS: &utils.TLSConfig{ + CertFile: certPath, + KeyFile: keyPath, + }, + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, // Use nil for simplicity in tests + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, + }, + expectError: false, + }, + { + name: "successful connection addition with API key", + input: AddConnInput{ + Target: &utils.TargetConfig{ + ProxyId: "test-proxy-id-api", + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + ApiKey: "test-api-key", + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, }, expectError: false, }, { name: "invalid certificate path", input: AddConnInput{ - ProxyId: "test-proxy-id", - Target: "localhost:7233", - TLSCertPath: "/nonexistent/cert.pem", - TLSKeyPath: keyPath, - EncryptionKeyID: "test-key-id", - Namespace: "test-namespace", - AuthManager: nil, - AuthType: "jwt", + Target: &utils.TargetConfig{ + ProxyId: "test-proxy-id", + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + TLS: &utils.TLSConfig{ + CertFile: "/nonexistent/cert.pem", + KeyFile: keyPath, + }, + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, }, expectError: true, }, { name: "invalid key path", input: AddConnInput{ - ProxyId: "test-proxy-id", - Target: "localhost:7233", - TLSCertPath: certPath, - TLSKeyPath: "/nonexistent/key.pem", - EncryptionKeyID: "test-key-id", - Namespace: "test-namespace", - AuthManager: nil, - AuthType: "jwt", + Target: &utils.TargetConfig{ + ProxyId: "test-proxy-id", + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + TLS: &utils.TLSConfig{ + CertFile: certPath, + KeyFile: "/nonexistent/key.pem", + }, + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, }, expectError: true, }, { - name: "connection without auth manager", + name: "both API key and TLS configured - should error", input: AddConnInput{ - ProxyId: "test-proxy-id-no-auth", - Target: "localhost:7233", - TLSCertPath: certPath, - TLSKeyPath: keyPath, - EncryptionKeyID: "test-key-id", - Namespace: "test-namespace", - AuthManager: nil, - AuthType: "", + Target: &utils.TargetConfig{ + ProxyId: "test-proxy-id", + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + ApiKey: "test-api-key", + TLS: &utils.TLSConfig{ + CertFile: certPath, + KeyFile: keyPath, + }, + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, }, - expectError: false, + expectError: true, + errorMsg: "cannot have both api key and mtls authentication", }, } @@ -188,7 +253,7 @@ func TestConn_AddConn(t *testing.T) { assert.Equal(t, 1, len(conn.namespace)) // Verify the connection was stored correctly - nsConn, exists := conn.namespace[tt.input.ProxyId] + nsConn, exists := conn.namespace[tt.input.Target.ProxyId] assert.True(t, exists) assert.NotNil(t, nsConn.conn) assert.Equal(t, tt.input.AuthManager, nsConn.authManager) @@ -430,14 +495,24 @@ func TestConn_ConcurrentAccess(t *testing.T) { defer wg.Done() input := AddConnInput{ - ProxyId: fmt.Sprintf("proxy-id-%d", id), - Target: "localhost:7233", - TLSCertPath: certPath, - TLSKeyPath: keyPath, - EncryptionKeyID: "test-key-id", - Namespace: fmt.Sprintf("namespace-%d", id), - AuthManager: nil, - AuthType: "jwt", + Target: &utils.TargetConfig{ + ProxyId: fmt.Sprintf("proxy-id-%d", id), + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: fmt.Sprintf("namespace-%d", id), + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + TLS: &utils.TLSConfig{ + CertFile: certPath, + KeyFile: keyPath, + }, + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, } err := conn.AddConn(input) diff --git a/utils/config.go b/utils/config.go index 97c363d..39fbe4c 100644 --- a/utils/config.go +++ b/utils/config.go @@ -27,12 +27,21 @@ type CachingConfig struct { } type TargetConfig struct { - ProxyId string `yaml:"proxy_id"` - Target string `yaml:"target"` - TLS TLSConfig `yaml:"tls"` - EncryptionKey string `yaml:"encryption_key"` - Namespace string `yaml:"namespace"` - Authentication *AuthConfig `yaml:"authentication,omitempty"` + ProxyId string `yaml:"proxy_id"` + TemporalCloud TemporalCloudConfig `yaml:"temporal_cloud"` + EncryptionKey string `yaml:"encryption_key"` + Authentication *AuthConfig `yaml:"authentication,omitempty"` +} + +type TemporalCloudConfig struct { + Namespace string `yaml:"namespace"` + HostPort string `yaml:"host_port"` + Authentication TemporalAuthConfig `yaml:"authentication"` +} + +type TemporalAuthConfig struct { + TLS *TLSConfig `yaml:"tls,omitempty"` + ApiKey string `yaml:"api_key,omitempty"` } type TLSConfig struct { diff --git a/utils/config_test.go b/utils/config_test.go index 53e1f30..463d599 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -14,19 +14,28 @@ func TestConfig_UnmarshalYAML(t *testing.T) { wantErr bool }{ { - name: "valid complete config", + name: "valid complete config with TLS authentication", yamlData: ` server: port: 7233 host: "0.0.0.0" +metrics: + port: 8080 +encryption: + caching: + max_cache: 100 + max_age: "1h" + max_usage: 1000 targets: - proxy_id: "test.namespace.internal" - target: "test.namespace.tmprl.cloud:7233" - tls: - cert_file: "/path/to/cert.crt" - key_file: "/path/to/key.key" + temporal_cloud: + namespace: "test.namespace" + host_port: "test.namespace.tmprl.cloud:7233" + authentication: + tls: + cert_file: "/path/to/cert.crt" + key_file: "/path/to/key.key" encryption_key: "test-key" - namespace: "test.namespace" authentication: type: "spiffe" config: @@ -40,16 +49,30 @@ targets: Port: 7233, Host: "0.0.0.0", }, + Metrics: MetricsConfig{ + Port: 8080, + }, + Encryption: EncryptionConfig{ + Caching: CachingConfig{ + MaxCache: 100, + MaxAge: "1h", + MaxUsage: 1000, + }, + }, Targets: []TargetConfig{ { - ProxyId: "test.namespace.internal", - Target: "test.namespace.tmprl.cloud:7233", - EncryptionKey: "test-key", - Namespace: "test.namespace", - TLS: TLSConfig{ - CertFile: "/path/to/cert.crt", - KeyFile: "/path/to/key.key", + ProxyId: "test.namespace.internal", + TemporalCloud: TemporalCloudConfig{ + Namespace: "test.namespace", + HostPort: "test.namespace.tmprl.cloud:7233", + Authentication: TemporalAuthConfig{ + TLS: &TLSConfig{ + CertFile: "/path/to/cert.crt", + KeyFile: "/path/to/key.key", + }, + }, }, + EncryptionKey: "test-key", Authentication: &AuthConfig{ Type: "spiffe", Config: map[string]interface{}{ @@ -64,35 +87,44 @@ targets: wantErr: false, }, { - name: "minimal config without authentication", + name: "valid config with API key authentication", yamlData: ` server: port: 8080 host: "localhost" +metrics: + port: 9090 targets: - proxy_id: "simple.internal" - target: "simple.external:8080" - tls: - cert_file: "/cert.crt" - key_file: "/key.key" + temporal_cloud: + namespace: "simple" + host_port: "simple.external:8080" + authentication: + api_key: "your-api-key-here" encryption_key: "simple-key" - namespace: "simple" `, want: Config{ Server: ServerConfig{ Port: 8080, Host: "localhost", }, + Metrics: MetricsConfig{ + Port: 9090, + }, + Encryption: EncryptionConfig{ + Caching: CachingConfig{}, + }, Targets: []TargetConfig{ { - ProxyId: "simple.internal", - Target: "simple.external:8080", - EncryptionKey: "simple-key", - Namespace: "simple", - TLS: TLSConfig{ - CertFile: "/cert.crt", - KeyFile: "/key.key", + ProxyId: "simple.internal", + TemporalCloud: TemporalCloudConfig{ + Namespace: "simple", + HostPort: "simple.external:8080", + Authentication: TemporalAuthConfig{ + ApiKey: "your-api-key-here", + }, }, + EncryptionKey: "simple-key", Authentication: nil, }, }, @@ -100,26 +132,33 @@ targets: wantErr: false, }, { - name: "multiple targets", + name: "multiple targets with mixed authentication", yamlData: ` server: port: 9090 host: "127.0.0.1" +metrics: + port: 8081 +encryption: + caching: + max_cache: 50 targets: - proxy_id: "target1.internal" - target: "target1.external:9090" - tls: - cert_file: "/target1.crt" - key_file: "/target1.key" + temporal_cloud: + namespace: "namespace1" + host_port: "target1.external:9090" + authentication: + tls: + cert_file: "/target1.crt" + key_file: "/target1.key" encryption_key: "key1" - namespace: "namespace1" - proxy_id: "target2.internal" - target: "target2.external:9091" - tls: - cert_file: "/target2.crt" - key_file: "/target2.key" + temporal_cloud: + namespace: "namespace2" + host_port: "target2.external:9091" + authentication: + api_key: "target2-api-key" encryption_key: "key2" - namespace: "namespace2" authentication: type: "oauth" config: @@ -131,27 +170,40 @@ targets: Port: 9090, Host: "127.0.0.1", }, + Metrics: MetricsConfig{ + Port: 8081, + }, + Encryption: EncryptionConfig{ + Caching: CachingConfig{ + MaxCache: 50, + }, + }, Targets: []TargetConfig{ { - ProxyId: "target1.internal", - Target: "target1.external:9090", - EncryptionKey: "key1", - Namespace: "namespace1", - TLS: TLSConfig{ - CertFile: "/target1.crt", - KeyFile: "/target1.key", + ProxyId: "target1.internal", + TemporalCloud: TemporalCloudConfig{ + Namespace: "namespace1", + HostPort: "target1.external:9090", + Authentication: TemporalAuthConfig{ + TLS: &TLSConfig{ + CertFile: "/target1.crt", + KeyFile: "/target1.key", + }, + }, }, + EncryptionKey: "key1", Authentication: nil, }, { - ProxyId: "target2.internal", - Target: "target2.external:9091", - EncryptionKey: "key2", - Namespace: "namespace2", - TLS: TLSConfig{ - CertFile: "/target2.crt", - KeyFile: "/target2.key", + ProxyId: "target2.internal", + TemporalCloud: TemporalCloudConfig{ + Namespace: "namespace2", + HostPort: "target2.external:9091", + Authentication: TemporalAuthConfig{ + ApiKey: "target2-api-key", + }, }, + EncryptionKey: "key2", Authentication: &AuthConfig{ Type: "oauth", Config: map[string]interface{}{ @@ -244,14 +296,18 @@ func TestServerConfig_Validation(t *testing.T) { func TestTargetConfig_Structure(t *testing.T) { target := TargetConfig{ - ProxyId: "test.internal", - Target: "test.external:7233", - EncryptionKey: "test-key", - Namespace: "test-namespace", - TLS: TLSConfig{ - CertFile: "/path/to/cert.crt", - KeyFile: "/path/to/key.key", + ProxyId: "test.internal", + TemporalCloud: TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "test.external:7233", + Authentication: TemporalAuthConfig{ + TLS: &TLSConfig{ + CertFile: "/path/to/cert.crt", + KeyFile: "/path/to/key.key", + }, + }, }, + EncryptionKey: "test-key", Authentication: &AuthConfig{ Type: "spiffe", Config: map[string]interface{}{ @@ -263,20 +319,20 @@ func TestTargetConfig_Structure(t *testing.T) { if target.ProxyId != "test.internal" { t.Errorf("Expected ProxyId to be 'test.internal', got %s", target.ProxyId) } - if target.Target != "test.external:7233" { - t.Errorf("Expected Target to be 'test.external:7233', got %s", target.Target) + if target.TemporalCloud.HostPort != "test.external:7233" { + t.Errorf("Expected TemporalCloud.HostPort to be 'test.external:7233', got %s", target.TemporalCloud.HostPort) } if target.EncryptionKey != "test-key" { t.Errorf("Expected EncryptionKey to be 'test-key', got %s", target.EncryptionKey) } - if target.Namespace != "test-namespace" { - t.Errorf("Expected Namespace to be 'test-namespace', got %s", target.Namespace) + if target.TemporalCloud.Namespace != "test-namespace" { + t.Errorf("Expected TemporalCloud.Namespace to be 'test-namespace', got %s", target.TemporalCloud.Namespace) } - if target.TLS.CertFile != "/path/to/cert.crt" { - t.Errorf("Expected TLS.CertFile to be '/path/to/cert.crt', got %s", target.TLS.CertFile) + if target.TemporalCloud.Authentication.TLS.CertFile != "/path/to/cert.crt" { + t.Errorf("Expected TemporalCloud.Authentication.TLS.CertFile to be '/path/to/cert.crt', got %s", target.TemporalCloud.Authentication.TLS.CertFile) } - if target.TLS.KeyFile != "/path/to/key.key" { - t.Errorf("Expected TLS.KeyFile to be '/path/to/key.key', got %s", target.TLS.KeyFile) + if target.TemporalCloud.Authentication.TLS.KeyFile != "/path/to/key.key" { + t.Errorf("Expected TemporalCloud.Authentication.TLS.KeyFile to be '/path/to/key.key', got %s", target.TemporalCloud.Authentication.TLS.KeyFile) } if target.Authentication == nil { t.Error("Expected Authentication to not be nil") @@ -342,6 +398,155 @@ func TestAuthConfig_Types(t *testing.T) { } } +func TestMetricsConfig_Structure(t *testing.T) { + tests := []struct { + name string + config MetricsConfig + want int + }{ + { + name: "default metrics port", + config: MetricsConfig{Port: 8080}, + want: 8080, + }, + { + name: "custom metrics port", + config: MetricsConfig{Port: 9090}, + want: 9090, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.config.Port != tt.want { + t.Errorf("Expected Port to be %d, got %d", tt.want, tt.config.Port) + } + }) + } +} + +func TestEncryptionConfig_Structure(t *testing.T) { + tests := []struct { + name string + config EncryptionConfig + want CachingConfig + }{ + { + name: "full caching config", + config: EncryptionConfig{ + Caching: CachingConfig{ + MaxCache: 100, + MaxAge: "1h", + MaxUsage: 1000, + }, + }, + want: CachingConfig{ + MaxCache: 100, + MaxAge: "1h", + MaxUsage: 1000, + }, + }, + { + name: "partial caching config", + config: EncryptionConfig{ + Caching: CachingConfig{ + MaxCache: 50, + }, + }, + want: CachingConfig{ + MaxCache: 50, + }, + }, + { + name: "empty caching config", + config: EncryptionConfig{ + Caching: CachingConfig{}, + }, + want: CachingConfig{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.config.Caching.MaxCache != tt.want.MaxCache { + t.Errorf("Expected MaxCache to be %d, got %d", tt.want.MaxCache, tt.config.Caching.MaxCache) + } + if tt.config.Caching.MaxAge != tt.want.MaxAge { + t.Errorf("Expected MaxAge to be %s, got %s", tt.want.MaxAge, tt.config.Caching.MaxAge) + } + if tt.config.Caching.MaxUsage != tt.want.MaxUsage { + t.Errorf("Expected MaxUsage to be %d, got %d", tt.want.MaxUsage, tt.config.Caching.MaxUsage) + } + }) + } +} + +func TestTemporalAuthConfig_Structure(t *testing.T) { + tests := []struct { + name string + config TemporalAuthConfig + desc string + }{ + { + name: "TLS authentication", + config: TemporalAuthConfig{ + TLS: &TLSConfig{ + CertFile: "/path/to/cert.crt", + KeyFile: "/path/to/key.key", + }, + }, + desc: "should have TLS config and no API key", + }, + { + name: "API key authentication", + config: TemporalAuthConfig{ + ApiKey: "test-api-key", + }, + desc: "should have API key and no TLS config", + }, + { + name: "empty authentication", + config: TemporalAuthConfig{}, + desc: "should have neither TLS nor API key", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + switch tt.name { + case "TLS authentication": + if tt.config.TLS == nil { + t.Error("Expected TLS to not be nil") + } else { + if tt.config.TLS.CertFile != "/path/to/cert.crt" { + t.Errorf("Expected CertFile to be '/path/to/cert.crt', got %s", tt.config.TLS.CertFile) + } + if tt.config.TLS.KeyFile != "/path/to/key.key" { + t.Errorf("Expected KeyFile to be '/path/to/key.key', got %s", tt.config.TLS.KeyFile) + } + } + if tt.config.ApiKey != "" { + t.Errorf("Expected ApiKey to be empty, got %s", tt.config.ApiKey) + } + case "API key authentication": + if tt.config.ApiKey != "test-api-key" { + t.Errorf("Expected ApiKey to be 'test-api-key', got %s", tt.config.ApiKey) + } + if tt.config.TLS != nil { + t.Error("Expected TLS to be nil") + } + case "empty authentication": + if tt.config.TLS != nil { + t.Error("Expected TLS to be nil") + } + if tt.config.ApiKey != "" { + t.Errorf("Expected ApiKey to be empty, got %s", tt.config.ApiKey) + } + } + }) + } +} + // Helper function to compare Config structs func configEqual(a, b Config) bool { if a.Server.Port != b.Server.Port || a.Server.Host != b.Server.Host { @@ -363,14 +568,33 @@ func configEqual(a, b Config) bool { } func targetConfigEqual(a, b TargetConfig) bool { - if a.ProxyId != b.ProxyId || a.Target != b.Target || a.EncryptionKey != b.EncryptionKey || a.Namespace != b.Namespace { + if a.ProxyId != b.ProxyId || a.EncryptionKey != b.EncryptionKey { return false } - if a.TLS.CertFile != b.TLS.CertFile || a.TLS.KeyFile != b.TLS.KeyFile { + // Compare TemporalCloud configuration + if a.TemporalCloud.Namespace != b.TemporalCloud.Namespace || a.TemporalCloud.HostPort != b.TemporalCloud.HostPort { return false } + // Compare TemporalCloud Authentication + if a.TemporalCloud.Authentication.ApiKey != b.TemporalCloud.Authentication.ApiKey { + return false + } + + // Compare TLS configuration + if (a.TemporalCloud.Authentication.TLS == nil) != (b.TemporalCloud.Authentication.TLS == nil) { + return false + } + + if a.TemporalCloud.Authentication.TLS != nil && b.TemporalCloud.Authentication.TLS != nil { + if a.TemporalCloud.Authentication.TLS.CertFile != b.TemporalCloud.Authentication.TLS.CertFile || + a.TemporalCloud.Authentication.TLS.KeyFile != b.TemporalCloud.Authentication.TLS.KeyFile { + return false + } + } + + // Compare proxy Authentication (spiffe, oauth, etc.) if (a.Authentication == nil) != (b.Authentication == nil) { return false } From ae15c34fb40d11e224557a5a8d5b66f64b1acfe3 Mon Sep 17 00:00:00 2001 From: Brendan Myers Date: Thu, 10 Jul 2025 10:05:39 +1000 Subject: [PATCH 2/3] feat: use env var for api key --- Makefile | 2 +- config.yaml.sample | 18 ++++--- proxy/proxy.go | 29 ++++++++-- proxy/proxy_test.go | 33 ++++++++++-- utils/config.go | 9 +++- utils/config_test.go | 125 +++++++++++++++++++++++++++++++++++++------ 6 files changed, 183 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 5bca199..d3a3ab3 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ OUTPUT_PATH := $(OUTPUT_DIR)/$(BINARY_NAME) .PHONY: all build clean test test-verbose test-coverage test-race test-short test-clean benchmark test-auth test-crypto test-proxy test-utils -all: build +all: test build build: go build -o $(OUTPUT_PATH) $(CMD_DIR) diff --git a/config.yaml.sample b/config.yaml.sample index 6c60903..533ce17 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -12,17 +12,18 @@ encryption: max_usage: 100 targets: - - proxy_id: "..internal" + - proxy_id: "" temporal_cloud: namespace: "." host_port: "..tmprl.cloud:7233" # endpoint when using mTLS # host_port: "..api.temporal.io:7233" # endpoint when using API keys - authentication: - # only set either tls or api_key + authentication: # only set either tls or api_key, not both tls: cert_file: "/path/to/./tls.crt" key_file: "/path/to/./tls.key" - api_key: "" + api_key: # only set either value or env, not both + value: "" + env: encryption_key: "" authentication: type: "spiffe" @@ -32,17 +33,18 @@ targets: audiences: - "temporal_cloud_proxy" - - proxy_id: "..internal" + - proxy_id: "" temporal_cloud: namespace: "." host_port: "..tmprl.cloud:7233" # endpoint when using mTLS # host_port: "..api.temporal.io:7233" # endpoint when using API keys - authentication: - # only set either tls or api_key + authentication: # only set either tls or api_key, not both tls: cert_file: "/path/to/./tls.crt" key_file: "/path/to/./tls.key" - api_key: "ey..." + api_key: # only set either value or env, not both + value: "" + env: encryption_key: "" authentication: type: "spiffe" diff --git a/proxy/proxy.go b/proxy/proxy.go index add6df0..5d7e8ab 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -69,7 +69,14 @@ func (mc *Conn) AddConn(input AddConnInput) error { fmt.Printf("Adding connection id: %s namespace: %s hostport: %s\n", input.Target.ProxyId, input.Target.TemporalCloud.Namespace, input.Target.TemporalCloud.HostPort) - if input.Target.TemporalCloud.Authentication.ApiKey != "" && input.Target.TemporalCloud.Authentication.TLS != nil { + mc.mu.RLock() + _, exists := mc.namespace[input.Target.ProxyId] + mc.mu.RUnlock() + if exists { + return fmt.Errorf("proxy-id %s already exists", input.Target.ProxyId) + } + + if input.Target.TemporalCloud.Authentication.ApiKey != nil && input.Target.TemporalCloud.Authentication.TLS != nil { return fmt.Errorf("%s: cannot have both api key and mtls authentication configured on a single target", input.Target.ProxyId) } @@ -102,7 +109,23 @@ func (mc *Conn) AddConn(input AddConnInput) error { clientInterceptor, } - if input.Target.TemporalCloud.Authentication.ApiKey != "" { + if apiKeyConfig := input.Target.TemporalCloud.Authentication.ApiKey; apiKeyConfig != nil { + if apiKeyConfig.Value != "" && apiKeyConfig.EnvVar != "" { + // TODO proper logging + fmt.Printf("WARN - multiple values provided for api key, using value. proxy_id: %s\n", input.Target.ProxyId) + } + + apiKey := "" + if apiKeyConfig.Value != "" { + apiKey = apiKeyConfig.Value + } else if apiKeyConfig.EnvVar != "" { + apiKey = os.Getenv(apiKeyConfig.EnvVar) + } + + if apiKey == "" { + return fmt.Errorf("%s: no api key provided", input.Target.ProxyId) + } + grpcInterceptors = append(grpcInterceptors, func(ctx context.Context, method string, req any, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { md, ok := metadata.FromIncomingContext(ctx) @@ -114,7 +137,7 @@ func (mc *Conn) AddConn(input AddConnInput) error { ctx = metadata.NewOutgoingContext(ctx, md) ctx = metadata.AppendToOutgoingContext(ctx, "temporal-namespace", input.Target.TemporalCloud.Namespace) - ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+input.Target.TemporalCloud.Authentication.ApiKey) + ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+apiKey) } return invoker(ctx, method, req, reply, cc, opts...) diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 1b89a20..7e6420a 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -142,7 +142,7 @@ func TestConn_AddConn(t *testing.T) { expectError: false, }, { - name: "successful connection addition with API key", + name: "successful connection addition with API key (value)", input: AddConnInput{ Target: &utils.TargetConfig{ ProxyId: "test-proxy-id-api", @@ -150,7 +150,9 @@ func TestConn_AddConn(t *testing.T) { Namespace: "test-namespace", HostPort: "localhost:7233", Authentication: utils.TemporalAuthConfig{ - ApiKey: "test-api-key", + ApiKey: &utils.TemporalApiKeyConfig{ + Value: "test-api-key", + }, }, }, EncryptionKey: "test-key-id", @@ -162,6 +164,29 @@ func TestConn_AddConn(t *testing.T) { }, expectError: false, }, + { + name: "successful connection addition with API key (env var)", + input: AddConnInput{ + Target: &utils.TargetConfig{ + ProxyId: "test-proxy-id-api-env", + TemporalCloud: utils.TemporalCloudConfig{ + Namespace: "test-namespace", + HostPort: "localhost:7233", + Authentication: utils.TemporalAuthConfig{ + ApiKey: &utils.TemporalApiKeyConfig{ + EnvVar: "TEST_TEMPORAL_API_KEY", + }, + }, + }, + EncryptionKey: "test-key-id", + }, + AuthManager: nil, + AuthType: "jwt", + MetricsHandler: metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{}), + CryptoCachingConfig: nil, + }, + expectError: true, // Will fail because env var is not set + }, { name: "invalid certificate path", input: AddConnInput{ @@ -219,7 +244,9 @@ func TestConn_AddConn(t *testing.T) { Namespace: "test-namespace", HostPort: "localhost:7233", Authentication: utils.TemporalAuthConfig{ - ApiKey: "test-api-key", + ApiKey: &utils.TemporalApiKeyConfig{ + Value: "test-api-key", + }, TLS: &utils.TLSConfig{ CertFile: certPath, KeyFile: keyPath, diff --git a/utils/config.go b/utils/config.go index 39fbe4c..cb32c2d 100644 --- a/utils/config.go +++ b/utils/config.go @@ -40,8 +40,13 @@ type TemporalCloudConfig struct { } type TemporalAuthConfig struct { - TLS *TLSConfig `yaml:"tls,omitempty"` - ApiKey string `yaml:"api_key,omitempty"` + TLS *TLSConfig `yaml:"tls,omitempty"` + ApiKey *TemporalApiKeyConfig `yaml:"api_key,omitempty"` +} + +type TemporalApiKeyConfig struct { + Value string `yaml:"value,omitempty"` + EnvVar string `yaml:"env,omitempty"` } type TLSConfig struct { diff --git a/utils/config_test.go b/utils/config_test.go index 463d599..6ef2639 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -87,7 +87,7 @@ targets: wantErr: false, }, { - name: "valid config with API key authentication", + name: "valid config with API key authentication (value)", yamlData: ` server: port: 8080 @@ -100,7 +100,8 @@ targets: namespace: "simple" host_port: "simple.external:8080" authentication: - api_key: "your-api-key-here" + api_key: + value: "your-api-key-here" encryption_key: "simple-key" `, want: Config{ @@ -121,7 +122,57 @@ targets: Namespace: "simple", HostPort: "simple.external:8080", Authentication: TemporalAuthConfig{ - ApiKey: "your-api-key-here", + ApiKey: &TemporalApiKeyConfig{ + Value: "your-api-key-here", + }, + }, + }, + EncryptionKey: "simple-key", + Authentication: nil, + }, + }, + }, + wantErr: false, + }, + { + name: "valid config with API key authentication (env var)", + yamlData: ` +server: + port: 8080 + host: "localhost" +metrics: + port: 9090 +targets: + - proxy_id: "simple.internal" + temporal_cloud: + namespace: "simple" + host_port: "simple.external:8080" + authentication: + api_key: + env: "TEMPORAL_API_KEY" + encryption_key: "simple-key" +`, + want: Config{ + Server: ServerConfig{ + Port: 8080, + Host: "localhost", + }, + Metrics: MetricsConfig{ + Port: 9090, + }, + Encryption: EncryptionConfig{ + Caching: CachingConfig{}, + }, + Targets: []TargetConfig{ + { + ProxyId: "simple.internal", + TemporalCloud: TemporalCloudConfig{ + Namespace: "simple", + HostPort: "simple.external:8080", + Authentication: TemporalAuthConfig{ + ApiKey: &TemporalApiKeyConfig{ + EnvVar: "TEMPORAL_API_KEY", + }, }, }, EncryptionKey: "simple-key", @@ -157,7 +208,8 @@ targets: namespace: "namespace2" host_port: "target2.external:9091" authentication: - api_key: "target2-api-key" + api_key: + value: "target2-api-key" encryption_key: "key2" authentication: type: "oauth" @@ -200,7 +252,9 @@ targets: Namespace: "namespace2", HostPort: "target2.external:9091", Authentication: TemporalAuthConfig{ - ApiKey: "target2-api-key", + ApiKey: &TemporalApiKeyConfig{ + Value: "target2-api-key", + }, }, }, EncryptionKey: "key2", @@ -498,12 +552,23 @@ func TestTemporalAuthConfig_Structure(t *testing.T) { desc: "should have TLS config and no API key", }, { - name: "API key authentication", + name: "API key authentication with value", config: TemporalAuthConfig{ - ApiKey: "test-api-key", + ApiKey: &TemporalApiKeyConfig{ + Value: "test-api-key", + }, }, desc: "should have API key and no TLS config", }, + { + name: "API key authentication with env var", + config: TemporalAuthConfig{ + ApiKey: &TemporalApiKeyConfig{ + EnvVar: "TEMPORAL_API_KEY", + }, + }, + desc: "should have API key env var and no TLS config", + }, { name: "empty authentication", config: TemporalAuthConfig{}, @@ -525,12 +590,33 @@ func TestTemporalAuthConfig_Structure(t *testing.T) { t.Errorf("Expected KeyFile to be '/path/to/key.key', got %s", tt.config.TLS.KeyFile) } } - if tt.config.ApiKey != "" { - t.Errorf("Expected ApiKey to be empty, got %s", tt.config.ApiKey) + if tt.config.ApiKey != nil { + t.Error("Expected ApiKey to be nil") + } + case "API key authentication with value": + if tt.config.ApiKey == nil { + t.Error("Expected ApiKey to not be nil") + } else { + if tt.config.ApiKey.Value != "test-api-key" { + t.Errorf("Expected ApiKey.Value to be 'test-api-key', got %s", tt.config.ApiKey.Value) + } + if tt.config.ApiKey.EnvVar != "" { + t.Errorf("Expected ApiKey.EnvVar to be empty, got %s", tt.config.ApiKey.EnvVar) + } + } + if tt.config.TLS != nil { + t.Error("Expected TLS to be nil") } - case "API key authentication": - if tt.config.ApiKey != "test-api-key" { - t.Errorf("Expected ApiKey to be 'test-api-key', got %s", tt.config.ApiKey) + case "API key authentication with env var": + if tt.config.ApiKey == nil { + t.Error("Expected ApiKey to not be nil") + } else { + if tt.config.ApiKey.EnvVar != "TEMPORAL_API_KEY" { + t.Errorf("Expected ApiKey.EnvVar to be 'TEMPORAL_API_KEY', got %s", tt.config.ApiKey.EnvVar) + } + if tt.config.ApiKey.Value != "" { + t.Errorf("Expected ApiKey.Value to be empty, got %s", tt.config.ApiKey.Value) + } } if tt.config.TLS != nil { t.Error("Expected TLS to be nil") @@ -539,8 +625,8 @@ func TestTemporalAuthConfig_Structure(t *testing.T) { if tt.config.TLS != nil { t.Error("Expected TLS to be nil") } - if tt.config.ApiKey != "" { - t.Errorf("Expected ApiKey to be empty, got %s", tt.config.ApiKey) + if tt.config.ApiKey != nil { + t.Error("Expected ApiKey to be nil") } } }) @@ -577,11 +663,18 @@ func targetConfigEqual(a, b TargetConfig) bool { return false } - // Compare TemporalCloud Authentication - if a.TemporalCloud.Authentication.ApiKey != b.TemporalCloud.Authentication.ApiKey { + // Compare TemporalCloud Authentication - API Key + if (a.TemporalCloud.Authentication.ApiKey == nil) != (b.TemporalCloud.Authentication.ApiKey == nil) { return false } + if a.TemporalCloud.Authentication.ApiKey != nil && b.TemporalCloud.Authentication.ApiKey != nil { + if a.TemporalCloud.Authentication.ApiKey.Value != b.TemporalCloud.Authentication.ApiKey.Value || + a.TemporalCloud.Authentication.ApiKey.EnvVar != b.TemporalCloud.Authentication.ApiKey.EnvVar { + return false + } + } + // Compare TLS configuration if (a.TemporalCloud.Authentication.TLS == nil) != (b.TemporalCloud.Authentication.TLS == nil) { return false From a5ec7c25bd3af259163ae01d4e0d4a7bae341cac Mon Sep 17 00:00:00 2001 From: Brendan Myers Date: Thu, 10 Jul 2025 13:43:47 +1000 Subject: [PATCH 3/3] fix: rename 'targets' to 'workloads' --- cmd/main.go | 24 ++++---- config.yaml.sample | 6 +- proxy/proxy.go | 48 ++++++++-------- proxy/proxy_test.go | 74 ++++++++++++------------ utils/config.go | 6 +- utils/config_manager_test.go | 104 +++++++++++++++++---------------- utils/config_test.go | 108 +++++++++++++++++------------------ 7 files changed, 189 insertions(+), 181 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 3205819..72f2773 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -110,22 +110,22 @@ func main() { func configureProxy(proxyConns *proxy.Conn, cfg *utils.Config) error { ctx := context.TODO() - for _, t := range cfg.Targets { + for _, w := range cfg.Workloads { var authManager *auth.AuthManager var authType string - if t.Authentication != nil { + if w.Authentication != nil { authManager = auth.NewAuthManager() - authType = t.Authentication.Type + authType = w.Authentication.Type switch authType { case "spiffe": spiffeAuth := &auth.SpiffeAuthenticator{ - TrustDomain: t.Authentication.Config["trust_domain"].(string), - Endpoint: t.Authentication.Config["endpoint"].(string), + TrustDomain: w.Authentication.Config["trust_domain"].(string), + Endpoint: w.Authentication.Config["endpoint"].(string), } - if audiences, ok := t.Authentication.Config["audiences"].([]interface{}); ok { + if audiences, ok := w.Authentication.Config["audiences"].([]interface{}); ok { for _, a := range audiences { if audience, ok := a.(string); ok { spiffeAuth.Audiences = append(spiffeAuth.Audiences, audience) @@ -133,7 +133,7 @@ func configureProxy(proxyConns *proxy.Conn, cfg *utils.Config) error { } } - if err := spiffeAuth.Init(ctx, t.Authentication.Config); err != nil { + if err := spiffeAuth.Init(ctx, w.Authentication.Config); err != nil { return fmt.Errorf("failed to initialize spiffe authenticator: %w", err) } @@ -149,11 +149,11 @@ func configureProxy(proxyConns *proxy.Conn, cfg *utils.Config) error { metricsHandler := metrics.NewMetricsHandler(metrics.MetricsHandlerOptions{ // Todo: do we need these many attributes? InitialAttributes: attribute.NewSet( - attribute.String("proxy_id", t.ProxyId), - attribute.String("namespace", t.TemporalCloud.Namespace), - attribute.String("host_port", t.TemporalCloud.HostPort), + attribute.String("workload_id", w.WorkloadId), + attribute.String("namespace", w.TemporalCloud.Namespace), + attribute.String("host_port", w.TemporalCloud.HostPort), attribute.String("auth_type", authType), - attribute.String("encryption_key", t.EncryptionKey), + attribute.String("encryption_key", w.EncryptionKey), ), }) @@ -172,7 +172,7 @@ func configureProxy(proxyConns *proxy.Conn, cfg *utils.Config) error { } err := proxyConns.AddConn(proxy.AddConnInput{ - Target: &t, + Workload: &w, AuthManager: authManager, AuthType: authType, MetricsHandler: metricsHandler, diff --git a/config.yaml.sample b/config.yaml.sample index 533ce17..83d0d84 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -11,8 +11,8 @@ encryption: max_age: "10m" max_usage: 100 -targets: - - proxy_id: "" +workloads: + - workload_id: "" temporal_cloud: namespace: "." host_port: "..tmprl.cloud:7233" # endpoint when using mTLS @@ -33,7 +33,7 @@ targets: audiences: - "temporal_cloud_proxy" - - proxy_id: "" + - workload_id: "" temporal_cloud: namespace: "." host_port: "..tmprl.cloud:7233" # endpoint when using mTLS diff --git a/proxy/proxy.go b/proxy/proxy.go index 5d7e8ab..0814be5 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -57,7 +57,7 @@ func createKMSClient() *kms.KMS { // AddConnInput contains parameters for adding a new connection type AddConnInput struct { - Target *utils.TargetConfig + Workload *utils.WorkloadConfig AuthManager *auth.AuthManager AuthType string MetricsHandler metrics.MetricsHandler @@ -67,25 +67,25 @@ type AddConnInput struct { // AddConn adds a new connection to the proxy func (mc *Conn) AddConn(input AddConnInput) error { fmt.Printf("Adding connection id: %s namespace: %s hostport: %s\n", - input.Target.ProxyId, input.Target.TemporalCloud.Namespace, input.Target.TemporalCloud.HostPort) + input.Workload.WorkloadId, input.Workload.TemporalCloud.Namespace, input.Workload.TemporalCloud.HostPort) mc.mu.RLock() - _, exists := mc.namespace[input.Target.ProxyId] + _, exists := mc.namespace[input.Workload.WorkloadId] mc.mu.RUnlock() if exists { - return fmt.Errorf("proxy-id %s already exists", input.Target.ProxyId) + return fmt.Errorf("workload-id %s already exists", input.Workload.WorkloadId) } - if input.Target.TemporalCloud.Authentication.ApiKey != nil && input.Target.TemporalCloud.Authentication.TLS != nil { - return fmt.Errorf("%s: cannot have both api key and mtls authentication configured on a single target", - input.Target.ProxyId) + if input.Workload.TemporalCloud.Authentication.ApiKey != nil && input.Workload.TemporalCloud.Authentication.TLS != nil { + return fmt.Errorf("%s: cannot have both api key and mtls authentication configured on a single workload", + input.Workload.WorkloadId) } //Initialize AWS KMS client kmsClient := createKMSClient() codecContext := map[string]string{ - "namespace": input.Target.TemporalCloud.Namespace, + "namespace": input.Workload.TemporalCloud.Namespace, } clientInterceptor, err := converter.NewPayloadCodecGRPCClientInterceptor( @@ -93,7 +93,7 @@ func (mc *Conn) AddConn(input AddConnInput) error { Codecs: []converter.PayloadCodec{codec.NewEncryptionCodecWithCaching( kmsClient, codecContext, - input.Target.EncryptionKey, + input.Workload.EncryptionKey, input.MetricsHandler, input.CryptoCachingConfig, )}, @@ -109,10 +109,10 @@ func (mc *Conn) AddConn(input AddConnInput) error { clientInterceptor, } - if apiKeyConfig := input.Target.TemporalCloud.Authentication.ApiKey; apiKeyConfig != nil { + if apiKeyConfig := input.Workload.TemporalCloud.Authentication.ApiKey; apiKeyConfig != nil { if apiKeyConfig.Value != "" && apiKeyConfig.EnvVar != "" { // TODO proper logging - fmt.Printf("WARN - multiple values provided for api key, using value. proxy_id: %s\n", input.Target.ProxyId) + fmt.Printf("WARN - multiple values provided for api key, using value. workload-id: %s\n", input.Workload.WorkloadId) } apiKey := "" @@ -123,7 +123,7 @@ func (mc *Conn) AddConn(input AddConnInput) error { } if apiKey == "" { - return fmt.Errorf("%s: no api key provided", input.Target.ProxyId) + return fmt.Errorf("%s: no api key provided", input.Workload.WorkloadId) } grpcInterceptors = append(grpcInterceptors, @@ -136,15 +136,15 @@ func (mc *Conn) AddConn(input AddConnInput) error { md.Delete("temporal-namespace") ctx = metadata.NewOutgoingContext(ctx, md) - ctx = metadata.AppendToOutgoingContext(ctx, "temporal-namespace", input.Target.TemporalCloud.Namespace) + ctx = metadata.AppendToOutgoingContext(ctx, "temporal-namespace", input.Workload.TemporalCloud.Namespace) ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+apiKey) } return invoker(ctx, method, req, reply, cc, opts...) }) } else { - cert, err := tls.LoadX509KeyPair(input.Target.TemporalCloud.Authentication.TLS.CertFile, - input.Target.TemporalCloud.Authentication.TLS.KeyFile) + cert, err := tls.LoadX509KeyPair(input.Workload.TemporalCloud.Authentication.TLS.CertFile, + input.Workload.TemporalCloud.Authentication.TLS.KeyFile) if err != nil { return err } @@ -153,7 +153,7 @@ func (mc *Conn) AddConn(input AddConnInput) error { } conn, err := grpc.NewClient( - input.Target.TemporalCloud.HostPort, + input.Workload.TemporalCloud.HostPort, grpc.WithTransportCredentials(credentials.NewTLS( &tlsConfig, )), @@ -164,7 +164,7 @@ func (mc *Conn) AddConn(input AddConnInput) error { } mc.mu.Lock() - mc.namespace[input.Target.ProxyId] = NamespaceConn{ + mc.namespace[input.Workload.WorkloadId] = NamespaceConn{ conn: conn, authManager: input.AuthManager, authType: input.AuthType, @@ -202,21 +202,21 @@ func (mc *Conn) Invoke(ctx context.Context, method string, args interface{}, rep return status.Errorf(codes.InvalidArgument, "unable to read metadata") } - proxyId := md.Get("proxy-id") + workloadId := md.Get("workload-id") - if len(proxyId) <= 0 { - return status.Error(codes.InvalidArgument, "metadata missing proxy-id") + if len(workloadId) <= 0 { + return status.Error(codes.InvalidArgument, "metadata missing workload-id") } - if len(proxyId) != 1 { - return status.Error(codes.InvalidArgument, "metadata contains multiple proxy-id entries") + if len(workloadId) != 1 { + return status.Error(codes.InvalidArgument, "metadata contains multiple workload-id entries") } mc.mu.RLock() - namespace, exists := mc.namespace[proxyId[0]] + namespace, exists := mc.namespace[workloadId[0]] mc.mu.RUnlock() if !exists { - return status.Errorf(codes.InvalidArgument, "invalid proxy-id: %s", proxyId[0]) + return status.Errorf(codes.InvalidArgument, "invalid workload-id: %s", workloadId[0]) } if namespace.authManager != nil { diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 7e6420a..1d22f7c 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -120,8 +120,8 @@ func TestConn_AddConn(t *testing.T) { { name: "successful connection addition with TLS", input: AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: "test-proxy-id", + Workload: &utils.WorkloadConfig{ + WorkloadId: "test-workload-id", TemporalCloud: utils.TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "localhost:7233", @@ -144,8 +144,8 @@ func TestConn_AddConn(t *testing.T) { { name: "successful connection addition with API key (value)", input: AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: "test-proxy-id-api", + Workload: &utils.WorkloadConfig{ + WorkloadId: "test-workload-id-api", TemporalCloud: utils.TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "localhost:7233", @@ -167,8 +167,8 @@ func TestConn_AddConn(t *testing.T) { { name: "successful connection addition with API key (env var)", input: AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: "test-proxy-id-api-env", + Workload: &utils.WorkloadConfig{ + WorkloadId: "test-workload-id-api-env", TemporalCloud: utils.TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "localhost:7233", @@ -190,8 +190,8 @@ func TestConn_AddConn(t *testing.T) { { name: "invalid certificate path", input: AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: "test-proxy-id", + Workload: &utils.WorkloadConfig{ + WorkloadId: "test-workload-id", TemporalCloud: utils.TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "localhost:7233", @@ -214,8 +214,8 @@ func TestConn_AddConn(t *testing.T) { { name: "invalid key path", input: AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: "test-proxy-id", + Workload: &utils.WorkloadConfig{ + WorkloadId: "test-workload-id", TemporalCloud: utils.TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "localhost:7233", @@ -238,8 +238,8 @@ func TestConn_AddConn(t *testing.T) { { name: "both API key and TLS configured - should error", input: AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: "test-proxy-id", + Workload: &utils.WorkloadConfig{ + WorkloadId: "test-workload-id", TemporalCloud: utils.TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "localhost:7233", @@ -280,7 +280,7 @@ func TestConn_AddConn(t *testing.T) { assert.Equal(t, 1, len(conn.namespace)) // Verify the connection was stored correctly - nsConn, exists := conn.namespace[tt.input.Target.ProxyId] + nsConn, exists := conn.namespace[tt.input.Workload.WorkloadId] assert.True(t, exists) assert.NotNil(t, nsConn.conn) assert.Equal(t, tt.input.AuthManager, nsConn.authManager) @@ -321,7 +321,7 @@ func TestConn_Invoke(t *testing.T) { expectedCode: codes.InvalidArgument, }, { - name: "missing proxy-id", + name: "missing workload-id", setupContext: func() context.Context { md := metadata.New(map[string]string{}) return metadata.NewIncomingContext(context.Background(), md) @@ -332,14 +332,14 @@ func TestConn_Invoke(t *testing.T) { method: "/test.Service/Method", expectError: true, expectedCode: codes.InvalidArgument, - errorContains: "metadata missing proxy-id", + errorContains: "metadata missing workload-id", }, { - name: "multiple proxy-id entries", + name: "multiple workload-id entries", setupContext: func() context.Context { md := metadata.New(map[string]string{}) - md.Append("proxy-id", "proxy-id-1") - md.Append("proxy-id", "proxy-id-2") + md.Append("workload-id", "workload-id-1") + md.Append("workload-id", "workload-id-2") return metadata.NewIncomingContext(context.Background(), md) }, setupConn: func() *Conn { @@ -348,13 +348,13 @@ func TestConn_Invoke(t *testing.T) { method: "/test.Service/Method", expectError: true, expectedCode: codes.InvalidArgument, - errorContains: "multiple proxy-id entries", + errorContains: "multiple workload-id entries", }, { - name: "target not found", + name: "workload not found", setupContext: func() context.Context { md := metadata.New(map[string]string{ - "proxy-id": "nonexistent-proxy-id", + "workload-id": "nonexistent-workload-id", }) return metadata.NewIncomingContext(context.Background(), md) }, @@ -364,19 +364,19 @@ func TestConn_Invoke(t *testing.T) { method: "/test.Service/Method", expectError: true, expectedCode: codes.InvalidArgument, - errorContains: "invalid proxy-id: nonexistent-proxy-id", + errorContains: "invalid workload-id: nonexistent-workload-id", }, { name: "invoke without authentication - skips auth logic", setupContext: func() context.Context { md := metadata.New(map[string]string{ - "proxy-id": "test-proxy-id-no-auth", + "workload-id": "test-workload-id-no-auth", }) return metadata.NewIncomingContext(context.Background(), md) }, setupConn: func() *Conn { conn := NewConn() - // Don't add any namespace connections to test the "target not found" path + // Don't add any namespace connections to test the "workload not found" path // This way we can test the logic without hitting the nil pointer return conn }, @@ -385,13 +385,13 @@ func TestConn_Invoke(t *testing.T) { reply: struct{}{}, expectError: true, expectedCode: codes.InvalidArgument, - errorContains: "invalid proxy-id: test-proxy-id-no-auth", + errorContains: "invalid workload-id: test-workload-id-no-auth", }, { name: "missing authorization with auth manager", setupContext: func() context.Context { md := metadata.New(map[string]string{ - "proxy-id": "test-proxy-id", + "workload-id": "test-workload-id", }) return metadata.NewIncomingContext(context.Background(), md) }, @@ -400,7 +400,7 @@ func TestConn_Invoke(t *testing.T) { // Create a real auth manager for testing authManager := auth.NewAuthManager() - conn.namespace["test-proxy-id"] = NamespaceConn{ + conn.namespace["test-workload-id"] = NamespaceConn{ conn: nil, authManager: authManager, authType: "jwt", @@ -416,7 +416,7 @@ func TestConn_Invoke(t *testing.T) { name: "multiple authorization entries", setupContext: func() context.Context { md := metadata.New(map[string]string{ - "proxy-id": "test-proxy-id", + "workload-id": "test-workload-id", }) md.Append("authorization", "Bearer token1") md.Append("authorization", "Bearer token2") @@ -427,7 +427,7 @@ func TestConn_Invoke(t *testing.T) { // Create a real auth manager for testing authManager := auth.NewAuthManager() - conn.namespace["test-proxy-id"] = NamespaceConn{ + conn.namespace["test-workload-id"] = NamespaceConn{ conn: nil, authManager: authManager, authType: "jwt", @@ -522,8 +522,8 @@ func TestConn_ConcurrentAccess(t *testing.T) { defer wg.Done() input := AddConnInput{ - Target: &utils.TargetConfig{ - ProxyId: fmt.Sprintf("proxy-id-%d", id), + Workload: &utils.WorkloadConfig{ + WorkloadId: fmt.Sprintf("workload-id-%d", id), TemporalCloud: utils.TemporalCloudConfig{ Namespace: fmt.Sprintf("namespace-%d", id), HostPort: "localhost:7233", @@ -560,9 +560,9 @@ func TestConn_ConcurrentAccess(t *testing.T) { go func(id int) { defer wg.Done() - proxyId := id % numConnections + workloadId := id % numConnections md := metadata.New(map[string]string{ - "proxy-id": fmt.Sprintf("proxy-id-%d", proxyId), + "workload-id": fmt.Sprintf("workload-id-%d", workloadId), }) ctx := metadata.NewIncomingContext(context.Background(), md) @@ -610,7 +610,7 @@ func TestConn_InvokeWithAuthentication(t *testing.T) { name: "missing authorization header", setupContext: func() context.Context { md := metadata.New(map[string]string{ - "proxy-id": "test-proxy-id", + "workload-id": "test-workload-id", }) return metadata.NewIncomingContext(context.Background(), md) }, @@ -621,7 +621,7 @@ func TestConn_InvokeWithAuthentication(t *testing.T) { } // Add a namespace with auth manager (using nil since we can't easily mock the interface) - conn.namespace["test-proxy-id"] = NamespaceConn{ + conn.namespace["test-workload-id"] = NamespaceConn{ conn: nil, // Will cause failure, but we're testing auth logic first authManager: nil, // We'll set this to non-nil to trigger auth checks authType: "jwt", @@ -630,9 +630,9 @@ func TestConn_InvokeWithAuthentication(t *testing.T) { // Set authManager to non-nil to trigger the auth logic // Use a real auth manager since we can't easily mock the interface authManager := auth.NewAuthManager() - nsConn := conn.namespace["test-proxy-id"] + nsConn := conn.namespace["test-workload-id"] nsConn.authManager = authManager - conn.namespace["test-proxy-id"] = nsConn + conn.namespace["test-workload-id"] = nsConn for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/utils/config.go b/utils/config.go index cb32c2d..c886075 100644 --- a/utils/config.go +++ b/utils/config.go @@ -4,7 +4,7 @@ type Config struct { Server ServerConfig `yaml:"server"` Metrics MetricsConfig `yaml:"metrics"` Encryption EncryptionConfig `yaml:"encryption"` - Targets []TargetConfig `yaml:"targets"` + Workloads []WorkloadConfig `yaml:"workloads"` } type ServerConfig struct { @@ -26,8 +26,8 @@ type CachingConfig struct { MaxUsage int `yaml:"max_usage,omitempty"` } -type TargetConfig struct { - ProxyId string `yaml:"proxy_id"` +type WorkloadConfig struct { + WorkloadId string `yaml:"workload_id"` TemporalCloud TemporalCloudConfig `yaml:"temporal_cloud"` EncryptionKey string `yaml:"encryption_key"` Authentication *AuthConfig `yaml:"authentication,omitempty"` diff --git a/utils/config_manager_test.go b/utils/config_manager_test.go index c5c644c..7b75730 100644 --- a/utils/config_manager_test.go +++ b/utils/config_manager_test.go @@ -23,14 +23,16 @@ func TestNewConfigManager(t *testing.T) { server: port: 7233 host: "0.0.0.0" -targets: - - proxy_id: "test.internal" - target: "test.external:7233" - tls: - cert_file: "/path/to/cert.crt" - key_file: "/path/to/key.key" +workloads: + - workload_id: "test.internal" + temporal_cloud: + namespace: "test-namespace" + host_port: "test.external:7233" + authentication: + tls: + cert_file: "/path/to/cert.crt" + key_file: "/path/to/key.key" encryption_key: "test-key" - namespace: "test-namespace" `, wantErr: false, expectNil: false, @@ -42,11 +44,11 @@ targets: server: port: 8080 host: "localhost" -targets: [] +workloads: [] `, wantErr: false, expectNil: false, - description: "should handle minimal config with empty targets", + description: "should handle minimal config with empty workloads", }, { name: "invalid yaml", @@ -134,21 +136,25 @@ func TestConfigManager_GetConfig(t *testing.T) { server: port: 9090 host: "127.0.0.1" -targets: - - proxy_id: "test1.internal" - target: "test1.external:9090" - tls: - cert_file: "/test1.crt" - key_file: "/test1.key" +workloads: + - workload_id: "test1.internal" + temporal_cloud: + namespace: "namespace1" + host_port: "test1.external:9090" + authentication: + tls: + cert_file: "/test1.crt" + key_file: "/test1.key" encryption_key: "key1" - namespace: "namespace1" - - proxy_id: "test2.internal" - target: "test2.external:9091" - tls: - cert_file: "/test2.crt" - key_file: "/test2.key" + - workload_id: "test2.internal" + temporal_cloud: + namespace: "namespace2" + host_port: "test2.external:9091" + authentication: + tls: + cert_file: "/test2.crt" + key_file: "/test2.key" encryption_key: "key2" - namespace: "namespace2" authentication: type: "spiffe" config: @@ -182,30 +188,30 @@ targets: t.Errorf("Expected server host to be '127.0.0.1', got %s", config.Server.Host) } - // Verify targets - if len(config.Targets) != 2 { - t.Errorf("Expected 2 targets, got %d", len(config.Targets)) + // Verify workloads + if len(config.Workloads) != 2 { + t.Errorf("Expected 2 workloads, got %d", len(config.Workloads)) } - if len(config.Targets) >= 1 { - target1 := config.Targets[0] - if target1.ProxyId != "test1.internal" { - t.Errorf("Expected first target proxy_id to be 'test1.internal', got %s", target1.ProxyId) + if len(config.Workloads) >= 1 { + workload1 := config.Workloads[0] + if workload1.WorkloadId != "test1.internal" { + t.Errorf("Expected first workload workload_id to be 'test1.internal', got %s", workload1.WorkloadId) } - if target1.Authentication != nil { - t.Error("Expected first target to have no authentication") + if workload1.Authentication != nil { + t.Error("Expected first workload to have no authentication") } } - if len(config.Targets) >= 2 { - target2 := config.Targets[1] - if target2.ProxyId != "test2.internal" { - t.Errorf("Expected second target proxy_id to be 'test2.internal', got %s", target2.ProxyId) + if len(config.Workloads) >= 2 { + workload2 := config.Workloads[1] + if workload2.WorkloadId != "test2.internal" { + t.Errorf("Expected second workload workload_id to be 'test2.internal', got %s", workload2.WorkloadId) } - if target2.Authentication == nil { - t.Error("Expected second target to have authentication") - } else if target2.Authentication.Type != "spiffe" { - t.Errorf("Expected second target auth type to be 'spiffe', got %s", target2.Authentication.Type) + if workload2.Authentication == nil { + t.Error("Expected second workload to have authentication") + } else if workload2.Authentication.Type != "spiffe" { + t.Errorf("Expected second workload auth type to be 'spiffe', got %s", workload2.Authentication.Type) } } } @@ -215,14 +221,16 @@ func TestConfigManager_GetConfig_ThreadSafety(t *testing.T) { server: port: 8080 host: "localhost" -targets: - - proxy_id: "concurrent.internal" - target: "concurrent.external:8080" - tls: - cert_file: "/concurrent.crt" - key_file: "/concurrent.key" +workloads: + - workload_id: "concurrent.internal" + temporal_cloud: + namespace: "concurrent-namespace" + host_port: "concurrent.external:8080" + authentication: + tls: + cert_file: "/concurrent.crt" + key_file: "/concurrent.key" encryption_key: "concurrent-key" - namespace: "concurrent-namespace" ` tmpDir := t.TempDir() @@ -259,11 +267,11 @@ targets: errors <- err return } - if len(config.Targets) != 1 { + if len(config.Workloads) != 1 { errors <- err return } - if config.Targets[0].ProxyId != "concurrent.internal" { + if config.Workloads[0].WorkloadId != "concurrent.internal" { errors <- err return } diff --git a/utils/config_test.go b/utils/config_test.go index 6ef2639..f955a73 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -26,8 +26,8 @@ encryption: max_cache: 100 max_age: "1h" max_usage: 1000 -targets: - - proxy_id: "test.namespace.internal" +workloads: + - workload_id: "test.namespace.internal" temporal_cloud: namespace: "test.namespace" host_port: "test.namespace.tmprl.cloud:7233" @@ -59,9 +59,9 @@ targets: MaxUsage: 1000, }, }, - Targets: []TargetConfig{ + Workloads: []WorkloadConfig{ { - ProxyId: "test.namespace.internal", + WorkloadId: "test.namespace.internal", TemporalCloud: TemporalCloudConfig{ Namespace: "test.namespace", HostPort: "test.namespace.tmprl.cloud:7233", @@ -94,8 +94,8 @@ server: host: "localhost" metrics: port: 9090 -targets: - - proxy_id: "simple.internal" +workloads: + - workload_id: "simple.internal" temporal_cloud: namespace: "simple" host_port: "simple.external:8080" @@ -115,9 +115,9 @@ targets: Encryption: EncryptionConfig{ Caching: CachingConfig{}, }, - Targets: []TargetConfig{ + Workloads: []WorkloadConfig{ { - ProxyId: "simple.internal", + WorkloadId: "simple.internal", TemporalCloud: TemporalCloudConfig{ Namespace: "simple", HostPort: "simple.external:8080", @@ -142,8 +142,8 @@ server: host: "localhost" metrics: port: 9090 -targets: - - proxy_id: "simple.internal" +workloads: + - workload_id: "simple.internal" temporal_cloud: namespace: "simple" host_port: "simple.external:8080" @@ -163,9 +163,9 @@ targets: Encryption: EncryptionConfig{ Caching: CachingConfig{}, }, - Targets: []TargetConfig{ + Workloads: []WorkloadConfig{ { - ProxyId: "simple.internal", + WorkloadId: "simple.internal", TemporalCloud: TemporalCloudConfig{ Namespace: "simple", HostPort: "simple.external:8080", @@ -183,7 +183,7 @@ targets: wantErr: false, }, { - name: "multiple targets with mixed authentication", + name: "multiple workloads with mixed authentication", yamlData: ` server: port: 9090 @@ -193,23 +193,23 @@ metrics: encryption: caching: max_cache: 50 -targets: - - proxy_id: "target1.internal" +workloads: + - workload_id: "workload1.internal" temporal_cloud: namespace: "namespace1" - host_port: "target1.external:9090" + host_port: "workload1.external:9090" authentication: tls: - cert_file: "/target1.crt" - key_file: "/target1.key" + cert_file: "/workload1.crt" + key_file: "/workload1.key" encryption_key: "key1" - - proxy_id: "target2.internal" + - workload_id: "workload2.internal" temporal_cloud: namespace: "namespace2" - host_port: "target2.external:9091" + host_port: "workload2.external:9091" authentication: api_key: - value: "target2-api-key" + value: "workload2-api-key" encryption_key: "key2" authentication: type: "oauth" @@ -230,16 +230,16 @@ targets: MaxCache: 50, }, }, - Targets: []TargetConfig{ + Workloads: []WorkloadConfig{ { - ProxyId: "target1.internal", + WorkloadId: "workload1.internal", TemporalCloud: TemporalCloudConfig{ Namespace: "namespace1", - HostPort: "target1.external:9090", + HostPort: "workload1.external:9090", Authentication: TemporalAuthConfig{ TLS: &TLSConfig{ - CertFile: "/target1.crt", - KeyFile: "/target1.key", + CertFile: "/workload1.crt", + KeyFile: "/workload1.key", }, }, }, @@ -247,13 +247,13 @@ targets: Authentication: nil, }, { - ProxyId: "target2.internal", + WorkloadId: "workload2.internal", TemporalCloud: TemporalCloudConfig{ Namespace: "namespace2", - HostPort: "target2.external:9091", + HostPort: "workload2.external:9091", Authentication: TemporalAuthConfig{ ApiKey: &TemporalApiKeyConfig{ - Value: "target2-api-key", + Value: "workload2-api-key", }, }, }, @@ -348,9 +348,9 @@ func TestServerConfig_Validation(t *testing.T) { } } -func TestTargetConfig_Structure(t *testing.T) { - target := TargetConfig{ - ProxyId: "test.internal", +func TestWorkloadConfig_Structure(t *testing.T) { + workload := WorkloadConfig{ + WorkloadId: "test.internal", TemporalCloud: TemporalCloudConfig{ Namespace: "test-namespace", HostPort: "test.external:7233", @@ -370,31 +370,31 @@ func TestTargetConfig_Structure(t *testing.T) { }, } - if target.ProxyId != "test.internal" { - t.Errorf("Expected ProxyId to be 'test.internal', got %s", target.ProxyId) + if workload.WorkloadId != "test.internal" { + t.Errorf("Expected WorkloadId to be 'test.internal', got %s", workload.WorkloadId) } - if target.TemporalCloud.HostPort != "test.external:7233" { - t.Errorf("Expected TemporalCloud.HostPort to be 'test.external:7233', got %s", target.TemporalCloud.HostPort) + if workload.TemporalCloud.HostPort != "test.external:7233" { + t.Errorf("Expected TemporalCloud.HostPort to be 'test.external:7233', got %s", workload.TemporalCloud.HostPort) } - if target.EncryptionKey != "test-key" { - t.Errorf("Expected EncryptionKey to be 'test-key', got %s", target.EncryptionKey) + if workload.EncryptionKey != "test-key" { + t.Errorf("Expected EncryptionKey to be 'test-key', got %s", workload.EncryptionKey) } - if target.TemporalCloud.Namespace != "test-namespace" { - t.Errorf("Expected TemporalCloud.Namespace to be 'test-namespace', got %s", target.TemporalCloud.Namespace) + if workload.TemporalCloud.Namespace != "test-namespace" { + t.Errorf("Expected TemporalCloud.Namespace to be 'test-namespace', got %s", workload.TemporalCloud.Namespace) } - if target.TemporalCloud.Authentication.TLS.CertFile != "/path/to/cert.crt" { - t.Errorf("Expected TemporalCloud.Authentication.TLS.CertFile to be '/path/to/cert.crt', got %s", target.TemporalCloud.Authentication.TLS.CertFile) + if workload.TemporalCloud.Authentication.TLS.CertFile != "/path/to/cert.crt" { + t.Errorf("Expected TemporalCloud.Authentication.TLS.CertFile to be '/path/to/cert.crt', got %s", workload.TemporalCloud.Authentication.TLS.CertFile) } - if target.TemporalCloud.Authentication.TLS.KeyFile != "/path/to/key.key" { - t.Errorf("Expected TemporalCloud.Authentication.TLS.KeyFile to be '/path/to/key.key', got %s", target.TemporalCloud.Authentication.TLS.KeyFile) + if workload.TemporalCloud.Authentication.TLS.KeyFile != "/path/to/key.key" { + t.Errorf("Expected TemporalCloud.Authentication.TLS.KeyFile to be '/path/to/key.key', got %s", workload.TemporalCloud.Authentication.TLS.KeyFile) } - if target.Authentication == nil { + if workload.Authentication == nil { t.Error("Expected Authentication to not be nil") } else { - if target.Authentication.Type != "spiffe" { - t.Errorf("Expected Authentication.Type to be 'spiffe', got %s", target.Authentication.Type) + if workload.Authentication.Type != "spiffe" { + t.Errorf("Expected Authentication.Type to be 'spiffe', got %s", workload.Authentication.Type) } - if trustDomain, ok := target.Authentication.Config["trust_domain"]; !ok || trustDomain != "spiffe://example.org/" { + if trustDomain, ok := workload.Authentication.Config["trust_domain"]; !ok || trustDomain != "spiffe://example.org/" { t.Errorf("Expected trust_domain to be 'spiffe://example.org/', got %v", trustDomain) } } @@ -639,13 +639,13 @@ func configEqual(a, b Config) bool { return false } - if len(a.Targets) != len(b.Targets) { + if len(a.Workloads) != len(b.Workloads) { return false } - for i, targetA := range a.Targets { - targetB := b.Targets[i] - if !targetConfigEqual(targetA, targetB) { + for i, workloadA := range a.Workloads { + workloadB := b.Workloads[i] + if !workloadConfigEqual(workloadA, workloadB) { return false } } @@ -653,8 +653,8 @@ func configEqual(a, b Config) bool { return true } -func targetConfigEqual(a, b TargetConfig) bool { - if a.ProxyId != b.ProxyId || a.EncryptionKey != b.EncryptionKey { +func workloadConfigEqual(a, b WorkloadConfig) bool { + if a.WorkloadId != b.WorkloadId || a.EncryptionKey != b.EncryptionKey { return false }