|
|
@@ -1752,3 +1752,294 @@ func TestConfigMapWithRedactedSecrets(t *testing.T) {
|
|
|
t.Fatalf("Expected ADMIN_PASSWORD value to be redacted, got '%s'", configMap[0].Value)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+func TestValidateOIDCProviderRequiresDiscoveryEndpoint(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"OAUTH2_PROVIDER=oidc"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ err := configParser.options.Validate()
|
|
|
+ if err == nil {
|
|
|
+ t.Fatal("Expected error when OIDC provider is set without discovery endpoint")
|
|
|
+ }
|
|
|
+ if err.Error() != "OAUTH2_OIDC_DISCOVERY_ENDPOINT must be configured when using the OIDC provider" {
|
|
|
+ t.Fatalf("Unexpected error message: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateOIDCProviderWithDiscoveryEndpoint(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "OAUTH2_PROVIDER=oidc",
|
|
|
+ "OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid-configuration",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDisableLocalAuthWithoutAlternative(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"DISABLE_LOCAL_AUTH=1"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when local auth is disabled without alternative")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDisableLocalAuthWithOAuth2ButNoUserCreation(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "DISABLE_LOCAL_AUTH=1",
|
|
|
+ "OAUTH2_PROVIDER=oidc",
|
|
|
+ "OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid-configuration",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when local auth is disabled with OAuth2 but without user creation")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDisableLocalAuthWithOAuth2AndUserCreation(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "DISABLE_LOCAL_AUTH=1",
|
|
|
+ "OAUTH2_PROVIDER=oidc",
|
|
|
+ "OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://example.com/.well-known/openid-configuration",
|
|
|
+ "OAUTH2_USER_CREATION=1",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDisableLocalAuthWithAuthProxyButNoUserCreation(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "DISABLE_LOCAL_AUTH=1",
|
|
|
+ "AUTH_PROXY_HEADER=X-Forwarded-User",
|
|
|
+ "AUTH_PROXY_USER_CREATION=0",
|
|
|
+ "TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when local auth is disabled with auth proxy but without user creation")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDisableLocalAuthWithAuthProxyAndUserCreation(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "DISABLE_LOCAL_AUTH=1",
|
|
|
+ "AUTH_PROXY_HEADER=X-Forwarded-User",
|
|
|
+ "AUTH_PROXY_USER_CREATION=1",
|
|
|
+ "TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateAuthProxyRequiresTrustedNetworks(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"AUTH_PROXY_HEADER=X-Forwarded-User"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ err := configParser.options.Validate()
|
|
|
+ if err == nil {
|
|
|
+ t.Fatal("Expected error when auth proxy header is set without trusted networks")
|
|
|
+ }
|
|
|
+ if err.Error() != "TRUSTED_REVERSE_PROXY_NETWORKS must be configured when AUTH_PROXY_HEADER is used" {
|
|
|
+ t.Fatalf("Unexpected error message: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateAuthProxyWithTrustedNetworks(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "AUTH_PROXY_HEADER=X-Forwarded-User",
|
|
|
+ "TRUSTED_REVERSE_PROXY_NETWORKS=10.0.0.0/8",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateCertFileMissingKeyFile(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"CERT_FILE=/path/to/cert.pem"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when CERT_FILE is set without KEY_FILE")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateKeyFileMissingCertFile(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"KEY_FILE=/path/to/key.pem"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when KEY_FILE is set without CERT_FILE")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateCertFileAndKeyFile(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "CERT_FILE=/path/to/cert.pem",
|
|
|
+ "KEY_FILE=/path/to/key.pem",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateCertDomainAndCertFileMutuallyExclusive(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "CERT_DOMAIN=example.com",
|
|
|
+ "CERT_FILE=/path/to/cert.pem",
|
|
|
+ "KEY_FILE=/path/to/key.pem",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when both CERT_DOMAIN and CERT_FILE are set")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateCertDomainAlone(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"CERT_DOMAIN=example.com"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateMetricsUsernameWithoutPassword(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"METRICS_USERNAME=admin"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when METRICS_USERNAME is set without METRICS_PASSWORD")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateMetricsPasswordWithoutUsername(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{"METRICS_PASSWORD=secret"}); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when METRICS_PASSWORD is set without METRICS_USERNAME")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateMetricsUsernameAndPassword(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "METRICS_USERNAME=admin",
|
|
|
+ "METRICS_PASSWORD=secret",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDatabaseMinConnsGreaterThanMaxConns(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "DATABASE_MIN_CONNS=25",
|
|
|
+ "DATABASE_MAX_CONNS=10",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when DATABASE_MIN_CONNS > DATABASE_MAX_CONNS")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateDatabaseMinConnsEqualToMaxConns(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "DATABASE_MIN_CONNS=10",
|
|
|
+ "DATABASE_MAX_CONNS=10",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateSchedulerRoundRobinMinGreaterThanMax(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL=1440",
|
|
|
+ "SCHEDULER_ROUND_ROBIN_MAX_INTERVAL=60",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when SCHEDULER_ROUND_ROBIN_MIN_INTERVAL > SCHEDULER_ROUND_ROBIN_MAX_INTERVAL")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateSchedulerRoundRobinMinLessThanMax(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL=60",
|
|
|
+ "SCHEDULER_ROUND_ROBIN_MAX_INTERVAL=1440",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateSchedulerEntryFrequencyMinGreaterThanMax(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL=1440",
|
|
|
+ "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL=5",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err == nil {
|
|
|
+ t.Fatal("Expected error when SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL > SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestValidateSchedulerEntryFrequencyMinLessThanMax(t *testing.T) {
|
|
|
+ configParser := NewConfigParser()
|
|
|
+ if err := configParser.parseLines([]string{
|
|
|
+ "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL=5",
|
|
|
+ "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL=1440",
|
|
|
+ }); err != nil {
|
|
|
+ t.Fatalf("Unexpected parse error: %v", err)
|
|
|
+ }
|
|
|
+ if err := configParser.options.Validate(); err != nil {
|
|
|
+ t.Fatalf("Unexpected error: %v", err)
|
|
|
+ }
|
|
|
+}
|