Skip to content

Commit 95be9d7

Browse files
authored
Merge pull request #571 from LerianStudio/feat/add-multi-tenant-service-api-key
feat: add multi tenant service api key
2 parents 5461549 + 47c48ad commit 95be9d7

File tree

12 files changed

+92
-8
lines changed

12 files changed

+92
-8
lines changed

components/manager/.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,6 @@ MULTI_TENANT_ENABLED=false
162162
# Consecutive failures before circuit breaker opens
163163
#MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD=5
164164
# Seconds before circuit breaker resets (half-open)
165-
#MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC=30
165+
#MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC=30
166+
# Service API key for authenticating with Tenant Manager (required when MULTI_TENANT_ENABLED=true)
167+
#MULTI_TENANT_SERVICE_API_KEY=

components/manager/internal/bootstrap/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ type Config struct {
103103
MultiTenantIdleTimeoutSec int `env:"MULTI_TENANT_IDLE_TIMEOUT_SEC" default:"300"`
104104
MultiTenantCircuitBreakerThreshold int `env:"MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD" default:"5"`
105105
MultiTenantCircuitBreakerTimeoutSec int `env:"MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC" default:"30"`
106+
MultiTenantServiceAPIKey string `env:"MULTI_TENANT_SERVICE_API_KEY"`
106107
}
107108

108109
// Validate checks that all required configuration fields are present
@@ -196,6 +197,10 @@ func (c *Config) validateManagerMultiTenantFields(errs []string) []string {
196197
errs = append(errs, "MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC must be > 0 when MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD > 0 (default: 30)")
197198
}
198199

200+
if c.MultiTenantServiceAPIKey == "" {
201+
errs = append(errs, "MULTI_TENANT_SERVICE_API_KEY is required when MULTI_TENANT_ENABLED=true")
202+
}
203+
199204
return errs
200205
}
201206

components/manager/internal/bootstrap/config_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,35 @@ func TestConfig_Validate_ProductionRequiresSecureStorageAndRedis(t *testing.T) {
231231
assert.Contains(t, err.Error(), "OBJECT_STORAGE_ENDPOINT must use HTTPS in production")
232232
}
233233

234+
func TestConfig_Validate_MultiTenantRequiresServiceAPIKey(t *testing.T) {
235+
t.Parallel()
236+
237+
cfg := validManagerConfig()
238+
cfg.MultiTenantEnabled = true
239+
cfg.MultiTenantURL = "http://tenant-manager:8080"
240+
cfg.MultiTenantCircuitBreakerThreshold = 5
241+
cfg.MultiTenantCircuitBreakerTimeoutSec = 30
242+
cfg.MultiTenantServiceAPIKey = ""
243+
244+
err := cfg.Validate()
245+
require.Error(t, err)
246+
assert.Contains(t, err.Error(), "MULTI_TENANT_SERVICE_API_KEY is required when MULTI_TENANT_ENABLED=true")
247+
}
248+
249+
func TestConfig_Validate_MultiTenantValidWithServiceAPIKey(t *testing.T) {
250+
t.Parallel()
251+
252+
cfg := validManagerConfig()
253+
cfg.MultiTenantEnabled = true
254+
cfg.MultiTenantURL = "http://tenant-manager:8080"
255+
cfg.MultiTenantCircuitBreakerThreshold = 5
256+
cfg.MultiTenantCircuitBreakerTimeoutSec = 30
257+
cfg.MultiTenantServiceAPIKey = "test-api-key"
258+
259+
err := cfg.Validate()
260+
require.NoError(t, err)
261+
}
262+
234263
func TestConfig_Validate_ProductionRequiresSecureRabbitMQScheme(t *testing.T) {
235264
t.Parallel()
236265

components/manager/internal/bootstrap/init_tenant.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ func newTenantManagerClient(cfg *Config, logger log.Logger) (*tmclient.Client, e
120120
)
121121
}
122122

123+
clientOpts = append(clientOpts, tmclient.WithServiceAPIKey(cfg.MultiTenantServiceAPIKey))
124+
123125
if strings.HasPrefix(strings.ToLower(cfg.MultiTenantURL), "http://") && strings.ToLower(cfg.EnvName) != "production" {
124126
clientOpts = append(clientOpts, tmclient.WithAllowInsecureHTTP())
125127
}

components/worker/.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,6 @@ MULTI_TENANT_ENABLED=false
119119
# Consecutive failures before circuit breaker opens
120120
#MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD=5
121121
# Seconds before circuit breaker resets (half-open)
122-
#MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC=30
122+
#MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC=30
123+
# Service API key for authenticating with Tenant Manager (required when MULTI_TENANT_ENABLED=true)
124+
#MULTI_TENANT_SERVICE_API_KEY=

components/worker/internal/bootstrap/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type Config struct {
6868
MultiTenantIdleTimeoutSec int `env:"MULTI_TENANT_IDLE_TIMEOUT_SEC" default:"300"`
6969
MultiTenantCircuitBreakerThreshold int `env:"MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD" default:"5"`
7070
MultiTenantCircuitBreakerTimeoutSec int `env:"MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC" default:"30"`
71+
MultiTenantServiceAPIKey string `env:"MULTI_TENANT_SERVICE_API_KEY"`
7172
}
7273

7374
// InitWorker initializes and configures the application's dependencies and returns the Service instance.

components/worker/internal/bootstrap/config_multitenant.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ func newTenantManagerClient(cfg *Config, logger clog.Logger) (*tmclient.Client,
6363
)
6464
}
6565

66+
clientOpts = append(clientOpts, tmclient.WithServiceAPIKey(cfg.MultiTenantServiceAPIKey))
67+
6668
if strings.HasPrefix(strings.ToLower(cfg.MultiTenantURL), "http://") && strings.ToLower(cfg.EnvName) != "production" {
6769
clientOpts = append(clientOpts, tmclient.WithAllowInsecureHTTP())
6870
}

components/worker/internal/bootstrap/config_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ func TestConfig_Validate_ProductionRequiresSecureStorageAndRedisWhenMultiTenant(
295295
cfg.MultiTenantURL = "https://tenant-manager.internal"
296296
cfg.MultiTenantCircuitBreakerThreshold = 5
297297
cfg.MultiTenantCircuitBreakerTimeoutSec = 30
298+
cfg.MultiTenantServiceAPIKey = "test-api-key"
298299
cfg.RedisHost = "redis:6379"
299300
cfg.RedisTLS = false
300301
cfg.RedisPassword = ""
@@ -309,6 +310,37 @@ func TestConfig_Validate_ProductionRequiresSecureStorageAndRedisWhenMultiTenant(
309310
assert.Contains(t, err.Error(), "OBJECT_STORAGE_ENDPOINT must use HTTPS in production")
310311
}
311312

313+
func TestConfig_Validate_MultiTenantRequiresServiceAPIKey(t *testing.T) {
314+
t.Parallel()
315+
316+
cfg := validWorkerConfig()
317+
cfg.MultiTenantEnabled = true
318+
cfg.MultiTenantURL = "http://tenant-manager:8080"
319+
cfg.MultiTenantCircuitBreakerThreshold = 5
320+
cfg.MultiTenantCircuitBreakerTimeoutSec = 30
321+
cfg.RedisHost = "redis:6379"
322+
cfg.MultiTenantServiceAPIKey = ""
323+
324+
err := cfg.Validate()
325+
require.Error(t, err)
326+
assert.Contains(t, err.Error(), "MULTI_TENANT_SERVICE_API_KEY is required when MULTI_TENANT_ENABLED=true")
327+
}
328+
329+
func TestConfig_Validate_MultiTenantValidWithServiceAPIKey(t *testing.T) {
330+
t.Parallel()
331+
332+
cfg := validWorkerConfig()
333+
cfg.MultiTenantEnabled = true
334+
cfg.MultiTenantURL = "http://tenant-manager:8080"
335+
cfg.MultiTenantCircuitBreakerThreshold = 5
336+
cfg.MultiTenantCircuitBreakerTimeoutSec = 30
337+
cfg.RedisHost = "redis:6379"
338+
cfg.MultiTenantServiceAPIKey = "test-api-key"
339+
340+
err := cfg.Validate()
341+
require.NoError(t, err)
342+
}
343+
312344
func TestConfig_Validate_ProductionRequiresSecureRabbitMQScheme(t *testing.T) {
313345
t.Parallel()
314346

components/worker/internal/bootstrap/config_validation.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ func (c *Config) multiTenantValidationErrors() []string {
9999
errs = append(errs, "REDIS_HOST is required when MULTI_TENANT_ENABLED=true (used for tenant discovery cache)")
100100
}
101101

102+
if c.MultiTenantServiceAPIKey == "" {
103+
errs = append(errs, "MULTI_TENANT_SERVICE_API_KEY is required when MULTI_TENANT_ENABLED=true")
104+
}
105+
102106
return errs
103107
}
104108

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.26
44

55
require (
66
github.com/LerianStudio/lib-auth/v2 v2.5.0-beta.7
7-
github.com/LerianStudio/lib-commons/v4 v4.0.0
7+
github.com/LerianStudio/lib-commons/v4 v4.1.0-beta.4
88
github.com/Masterminds/squirrel v1.5.4
99
github.com/Shopify/toxiproxy/v2 v2.12.0
1010
github.com/aws/aws-sdk-go-v2 v1.41.3

0 commit comments

Comments
 (0)