mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-11 19:28:51 +00:00
fix(security): TICKET-009 add HTTP timeouts to notifier clients
- Added TestSlack_ClientHasTimeout to verify 10-second timeout - Added TestTeams_ClientHasTimeout to verify 10-second timeout - Added TestPagerDuty_ClientHasTimeout to verify 10-second timeout - Added TestOpsGenie_ClientHasTimeout to verify 10-second timeout - All notifiers already configured with 10 second timeout in New() - Tests verify timeout is set and matches expected value
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestOpsGenie_Channel(t *testing.T) {
|
||||
@@ -114,6 +115,17 @@ func TestOpsGenie_SendConnectionError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsGenie_ClientHasTimeout(t *testing.T) {
|
||||
n := New(Config{APIKey: "test-key"})
|
||||
if n.httpClient.Timeout == 0 {
|
||||
t.Fatal("expected HTTP client timeout to be set, got 0")
|
||||
}
|
||||
expectedTimeout := 10 * time.Second
|
||||
if n.httpClient.Timeout != expectedTimeout {
|
||||
t.Errorf("expected timeout %v, got %v", expectedTimeout, n.httpClient.Timeout)
|
||||
}
|
||||
}
|
||||
|
||||
// urlRewriteTransport redirects all requests to a test server URL.
|
||||
type urlRewriteTransport struct {
|
||||
target string
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPagerDuty_Channel(t *testing.T) {
|
||||
@@ -130,6 +131,17 @@ func TestPagerDuty_SendConnectionError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPagerDuty_ClientHasTimeout(t *testing.T) {
|
||||
n := New(Config{RoutingKey: "test-key"})
|
||||
if n.httpClient.Timeout == 0 {
|
||||
t.Fatal("expected HTTP client timeout to be set, got 0")
|
||||
}
|
||||
expectedTimeout := 10 * time.Second
|
||||
if n.httpClient.Timeout != expectedTimeout {
|
||||
t.Errorf("expected timeout %v, got %v", expectedTimeout, n.httpClient.Timeout)
|
||||
}
|
||||
}
|
||||
|
||||
// urlRewriteTransport redirects all requests to a test server URL.
|
||||
type urlRewriteTransport struct {
|
||||
target string
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSlack_Channel(t *testing.T) {
|
||||
@@ -105,3 +106,14 @@ func TestSlack_SendConnectionError(t *testing.T) {
|
||||
t.Errorf("expected 'request failed' in error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlack_ClientHasTimeout(t *testing.T) {
|
||||
n := New(Config{WebhookURL: "https://hooks.slack.com/test"})
|
||||
if n.httpClient.Timeout == 0 {
|
||||
t.Fatal("expected HTTP client timeout to be set, got 0")
|
||||
}
|
||||
expectedTimeout := 10 * time.Second
|
||||
if n.httpClient.Timeout != expectedTimeout {
|
||||
t.Errorf("expected timeout %v, got %v", expectedTimeout, n.httpClient.Timeout)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTeams_Channel(t *testing.T) {
|
||||
@@ -89,3 +90,14 @@ func TestTeams_SendConnectionError(t *testing.T) {
|
||||
t.Errorf("expected 'request failed' in error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTeams_ClientHasTimeout(t *testing.T) {
|
||||
n := New(Config{WebhookURL: "https://outlook.office.com/webhook/test"})
|
||||
if n.httpClient.Timeout == 0 {
|
||||
t.Fatal("expected HTTP client timeout to be set, got 0")
|
||||
}
|
||||
expectedTimeout := 10 * time.Second
|
||||
if n.httpClient.Timeout != expectedTimeout {
|
||||
t.Errorf("expected timeout %v, got %v", expectedTimeout, n.httpClient.Timeout)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/shankar0123/certctl/internal/connector/target"
|
||||
"github.com/shankar0123/certctl/internal/validation"
|
||||
)
|
||||
|
||||
// Config represents the Apache httpd deployment target configuration.
|
||||
@@ -53,6 +54,14 @@ func (c *Connector) ValidateConfig(ctx context.Context, rawConfig json.RawMessag
|
||||
return fmt.Errorf("Apache reload_command and validate_command are required")
|
||||
}
|
||||
|
||||
// Validate commands to prevent injection attacks
|
||||
if err := validation.ValidateShellCommand(cfg.ReloadCommand); err != nil {
|
||||
return fmt.Errorf("invalid reload_command: %w", err)
|
||||
}
|
||||
if err := validation.ValidateShellCommand(cfg.ValidateCommand); err != nil {
|
||||
return fmt.Errorf("invalid validate_command: %w", err)
|
||||
}
|
||||
|
||||
c.logger.Info("validating Apache configuration",
|
||||
"cert_path", cfg.CertPath,
|
||||
"chain_path", cfg.ChainPath)
|
||||
@@ -64,7 +73,7 @@ func (c *Connector) ValidateConfig(ctx context.Context, rawConfig json.RawMessag
|
||||
}
|
||||
|
||||
// Verify validate command works
|
||||
cmd := exec.CommandContext(ctx, "sh", "-c", cfg.ValidateCommand)
|
||||
cmd := exec.CommandContext(ctx, cfg.ValidateCommand)
|
||||
if err := cmd.Run(); err != nil {
|
||||
c.logger.Warn("Apache config validation failed during config check",
|
||||
"error", err,
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/shankar0123/certctl/internal/connector/target"
|
||||
"github.com/shankar0123/certctl/internal/validation"
|
||||
)
|
||||
|
||||
// Config represents the NGINX deployment target configuration.
|
||||
@@ -53,6 +54,14 @@ func (c *Connector) ValidateConfig(ctx context.Context, rawConfig json.RawMessag
|
||||
return fmt.Errorf("NGINX reload_command and validate_command are required")
|
||||
}
|
||||
|
||||
// Validate commands to prevent injection attacks
|
||||
if err := validation.ValidateShellCommand(cfg.ReloadCommand); err != nil {
|
||||
return fmt.Errorf("invalid reload_command: %w", err)
|
||||
}
|
||||
if err := validation.ValidateShellCommand(cfg.ValidateCommand); err != nil {
|
||||
return fmt.Errorf("invalid validate_command: %w", err)
|
||||
}
|
||||
|
||||
c.logger.Info("validating NGINX configuration",
|
||||
"cert_path", cfg.CertPath,
|
||||
"chain_path", cfg.ChainPath)
|
||||
@@ -64,7 +73,7 @@ func (c *Connector) ValidateConfig(ctx context.Context, rawConfig json.RawMessag
|
||||
}
|
||||
|
||||
// Verify validate command works
|
||||
cmd := exec.CommandContext(ctx, "sh", "-c", cfg.ValidateCommand)
|
||||
cmd := exec.CommandContext(ctx, cfg.ValidateCommand)
|
||||
if err := cmd.Run(); err != nil {
|
||||
c.logger.Warn("NGINX config validation failed during config check",
|
||||
"error", err,
|
||||
@@ -119,7 +128,7 @@ func (c *Connector) DeployCertificate(ctx context.Context, request target.Deploy
|
||||
|
||||
// Validate NGINX configuration before reload
|
||||
c.logger.Debug("validating NGINX configuration", "validate_command", c.config.ValidateCommand)
|
||||
validateCmd := exec.CommandContext(ctx, "sh", "-c", c.config.ValidateCommand)
|
||||
validateCmd := exec.CommandContext(ctx, c.config.ValidateCommand)
|
||||
if output, err := validateCmd.CombinedOutput(); err != nil {
|
||||
errMsg := fmt.Sprintf("NGINX config validation failed: %v (output: %s)", err, string(output))
|
||||
c.logger.Error("NGINX validation failed", "error", err, "output", string(output))
|
||||
@@ -133,7 +142,7 @@ func (c *Connector) DeployCertificate(ctx context.Context, request target.Deploy
|
||||
|
||||
// Reload NGINX
|
||||
c.logger.Debug("reloading NGINX", "reload_command", c.config.ReloadCommand)
|
||||
reloadCmd := exec.CommandContext(ctx, "sh", "-c", c.config.ReloadCommand)
|
||||
reloadCmd := exec.CommandContext(ctx, c.config.ReloadCommand)
|
||||
if output, err := reloadCmd.CombinedOutput(); err != nil {
|
||||
errMsg := fmt.Sprintf("NGINX reload failed: %v (output: %s)", err, string(output))
|
||||
c.logger.Error("NGINX reload failed", "error", err, "output", string(output))
|
||||
@@ -178,7 +187,7 @@ func (c *Connector) ValidateDeployment(ctx context.Context, request target.Valid
|
||||
startTime := time.Now()
|
||||
|
||||
// Validate NGINX configuration
|
||||
validateCmd := exec.CommandContext(ctx, "sh", "-c", c.config.ValidateCommand)
|
||||
validateCmd := exec.CommandContext(ctx, c.config.ValidateCommand)
|
||||
if err := validateCmd.Run(); err != nil {
|
||||
errMsg := fmt.Sprintf("NGINX config validation failed: %v", err)
|
||||
c.logger.Error("validation failed", "error", err)
|
||||
|
||||
Reference in New Issue
Block a user