Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cmd/activity/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ type ActivityServerOptions struct {
ClickHousePassword string
ClickHouseTable string

// TLS configuration for ClickHouse connection
ClickHouseTLSEnabled bool
ClickHouseTLSCertFile string
ClickHouseTLSKeyFile string
ClickHouseTLSCAFile string

MaxQueryWindow time.Duration // Maximum time range allowed for queries
MaxPageSize int32 // Maximum number of results per page
}
Expand Down Expand Up @@ -173,6 +179,15 @@ func (o *ActivityServerOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.ClickHouseTable, "clickhouse-table", o.ClickHouseTable,
"Table containing audit events")

fs.BoolVar(&o.ClickHouseTLSEnabled, "clickhouse-tls-enabled", o.ClickHouseTLSEnabled,
"Enable TLS for ClickHouse connection")
fs.StringVar(&o.ClickHouseTLSCertFile, "clickhouse-tls-cert-file", o.ClickHouseTLSCertFile,
"Path to client certificate file for ClickHouse TLS")
fs.StringVar(&o.ClickHouseTLSKeyFile, "clickhouse-tls-key-file", o.ClickHouseTLSKeyFile,
"Path to client private key file for ClickHouse TLS")
fs.StringVar(&o.ClickHouseTLSCAFile, "clickhouse-tls-ca-file", o.ClickHouseTLSCAFile,
"Path to CA certificate file for ClickHouse TLS")

fs.DurationVar(&o.MaxQueryWindow, "max-query-window", o.MaxQueryWindow,
"Maximum time range for a single query (e.g., 720h for 30 days)")
fs.Int32Var(&o.MaxPageSize, "max-page-size", o.MaxPageSize,
Expand Down Expand Up @@ -234,6 +249,10 @@ func (o *ActivityServerOptions) Config() (*activityapiserver.Config, error) {
Username: o.ClickHouseUsername,
Password: o.ClickHousePassword,
Table: o.ClickHouseTable,
TLSEnabled: o.ClickHouseTLSEnabled,
TLSCertFile: o.ClickHouseTLSCertFile,
TLSKeyFile: o.ClickHouseTLSKeyFile,
TLSCAFile: o.ClickHouseTLSCAFile,
MaxQueryWindow: o.MaxQueryWindow,
MaxPageSize: o.MaxPageSize,
},
Expand Down
12 changes: 12 additions & 0 deletions config/base/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ spec:
- --clickhouse-table=$(CLICKHOUSE_TABLE)
- --clickhouse-username=$(CLICKHOUSE_USERNAME)
- --clickhouse-password=$(CLICKHOUSE_PASSWORD)
- --clickhouse-tls-enabled=$(CLICKHOUSE_TLS_ENABLED)
- --clickhouse-tls-cert-file=$(CLICKHOUSE_TLS_CERT_FILE)
- --clickhouse-tls-key-file=$(CLICKHOUSE_TLS_KEY_FILE)
- --clickhouse-tls-ca-file=$(CLICKHOUSE_TLS_CA_FILE)
- --authentication-tolerate-lookup-failure=$(AUTHENTICATION_TOLERATE_LOOKUP_FAILURE)
- --authorization-always-allow-paths=$(AUTHORIZATION_ALWAYS_ALLOW_PATHS)
- --logging-format=$(LOGGING_FORMAT)
Expand Down Expand Up @@ -82,6 +86,14 @@ spec:
name: clickhouse-credentials
key: password
optional: true
- name: CLICKHOUSE_TLS_ENABLED
value: "false"
- name: CLICKHOUSE_TLS_CERT_FILE
value: ""
- name: CLICKHOUSE_TLS_KEY_FILE
value: ""
- name: CLICKHOUSE_TLS_CA_FILE
value: ""
resources:
requests:
cpu: 100m
Expand Down
57 changes: 55 additions & 2 deletions internal/storage/clickhouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package storage
import (
"context"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"strings"
"time"

Expand Down Expand Up @@ -116,6 +119,12 @@ type ClickHouseConfig struct {
Password string
Table string

// TLS configuration (optional - disabled by default)
TLSEnabled bool // Enable TLS for ClickHouse connection
TLSCertFile string // Path to client certificate file
TLSKeyFile string // Path to client key file
TLSCAFile string // Path to CA certificate file

MaxQueryWindow time.Duration // Maximum allowed time range for queries
MaxPageSize int32 // Maximum results per page
}
Expand All @@ -128,7 +137,7 @@ type ClickHouseStorage struct {

// NewClickHouseStorage establishes a connection to ClickHouse and validates connectivity.
func NewClickHouseStorage(config ClickHouseConfig) (*ClickHouseStorage, error) {
conn, err := clickhouse.Open(&clickhouse.Options{
options := &clickhouse.Options{
Addr: []string{config.Address},
Auth: clickhouse.Auth{
Database: config.Database,
Expand All @@ -142,7 +151,19 @@ func NewClickHouseStorage(config ClickHouseConfig) (*ClickHouseStorage, error) {
Compression: &clickhouse.Compression{
Method: clickhouse.CompressionLZ4,
},
})
}

// Configure TLS if enabled
if config.TLSEnabled {
tlsConfig, err := loadTLSConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to load TLS configuration: %w", err)
}
options.TLS = tlsConfig
klog.V(2).Info("ClickHouse TLS enabled")
}

conn, err := clickhouse.Open(options)
if err != nil {
return nil, fmt.Errorf("failed to connect to ClickHouse: %w", err)
}
Expand All @@ -157,6 +178,38 @@ func NewClickHouseStorage(config ClickHouseConfig) (*ClickHouseStorage, error) {
}, nil
}

// loadTLSConfig loads TLS certificates and creates a tls.Config for ClickHouse connection.
func loadTLSConfig(config ClickHouseConfig) (*tls.Config, error) {
tlsConfig := &tls.Config{}

// Load client certificate and key if provided
if config.TLSCertFile != "" && config.TLSKeyFile != "" {
cert, err := tls.LoadX509KeyPair(config.TLSCertFile, config.TLSKeyFile)
if err != nil {
return nil, fmt.Errorf("failed to load client certificate: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
klog.V(2).Infof("Loaded client certificate from %s", config.TLSCertFile)
}

// Load CA certificate if provided
if config.TLSCAFile != "" {
caCert, err := os.ReadFile(config.TLSCAFile)
if err != nil {
return nil, fmt.Errorf("failed to read CA certificate: %w", err)
}

caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
return nil, fmt.Errorf("failed to parse CA certificate")
}
tlsConfig.RootCAs = caCertPool
klog.V(2).Infof("Loaded CA certificate from %s", config.TLSCAFile)
}

return tlsConfig, nil
}

func (s *ClickHouseStorage) Close() error {
if s.conn != nil {
return s.conn.Close()
Expand Down