From 691aea84c341e128230715324b6415a46e1eac17 Mon Sep 17 00:00:00 2001 From: Walnuts Date: Thu, 15 Jan 2026 10:59:59 +0900 Subject: [PATCH] feat: add TLS configuration options for Cassandra2 store (#7998) * feat: add TLS configuration options for Cassandra2 store Signed-off-by: walnuts1018 * fix: use 9142 port in tls connection Signed-off-by: walnuts1018 * Align the setting field names with gocql's SSLOpts. Signed-off-by: walnuts1018 * Removed: store.cluster.Port = 9142 * chore: update gocql dependency to v2 * refactor: improve Cassandra TLS configuration and port logic * docs: update filer.toml scaffold with ssl_enable_host_verification --------- Signed-off-by: walnuts1018 Co-authored-by: Chris Lu --- go.mod | 3 +- go.sum | 12 ++--- weed/command/scaffold/filer.toml | 8 +++ weed/filer/cassandra/cassandra_store.go | 2 +- weed/filer/cassandra/cassandra_store_kv.go | 2 +- weed/filer/cassandra2/cassandra_store.go | 54 ++++++++++++++++++++- weed/filer/cassandra2/cassandra_store_kv.go | 2 +- 7 files changed, 68 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index c83fa769f..824ed3ae4 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,6 @@ require ( github.com/go-redsync/redsync/v4 v4.15.0 github.com/go-sql-driver/mysql v1.9.3 github.com/go-zookeeper/zk v1.0.3 // indirect - github.com/gocql/gocql v1.7.0 github.com/golang/protobuf v1.5.4 github.com/golang/snappy v1.0.0 github.com/google/btree v1.1.3 @@ -37,7 +36,6 @@ require ( github.com/google/wire v0.7.0 // indirect github.com/googleapis/gax-go/v2 v2.15.0 // indirect github.com/gorilla/mux v1.8.1 - github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect @@ -121,6 +119,7 @@ require ( github.com/Jille/raft-grpc-transport v1.6.1 github.com/ThreeDotsLabs/watermill v1.5.1 github.com/a-h/templ v0.3.943 + github.com/apache/cassandra-gocql-driver/v2 v2.0.0 github.com/apple/foundationdb/bindings/go v0.0.0-20250911184653-27f7192f47c3 github.com/arangodb/go-driver v1.6.9 github.com/armon/go-metrics v0.4.1 diff --git a/go.sum b/go.sum index dccce8857..34c01ffc0 100644 --- a/go.sum +++ b/go.sum @@ -652,6 +652,8 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/cassandra-gocql-driver/v2 v2.0.0 h1:Omnzb1Z/P90Dr2TbVNu54ICQL7TKVIIsJO231w484HU= +github.com/apache/cassandra-gocql-driver/v2 v2.0.0/go.mod h1:QH/asJjB3mHvY6Dot6ZKMMpTcOrWJ8i9GhsvG1g0PK4= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apple/foundationdb/bindings/go v0.0.0-20250911184653-27f7192f47c3 h1:WZaTKNHCfcw7fWSR6/RKnCldVzvYZC+Y20Su4lffEIg= github.com/apple/foundationdb/bindings/go v0.0.0-20250911184653-27f7192f47c3/go.mod h1:OMVSB21p9+xQUIqlGizHPZfjK+SHws1ht+ZytVDoz9U= @@ -720,12 +722,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/biogo/store v0.0.0-20201120204734-aad293a2328f h1:+6okTAeUsUrdQr/qN7fIODzowrjjCrnJDg/gkYqcSXY= github.com/biogo/store v0.0.0-20201120204734-aad293a2328f/go.mod h1:z52shMwD6SGwRg2iYFjjDwX5Ene4ENTw6HfXraUy/08= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -1016,8 +1014,6 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/gocql/gocql v1.7.0 h1:O+7U7/1gSN7QTEAaMEsJc1Oq2QHXvCWoF3DFK9HDHus= -github.com/gocql/gocql v1.7.0/go.mod h1:vnlvXyFZeLBF0Wy+RS8hrOdbn0UWsWtdg07XJnFxZ+4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= @@ -1191,8 +1187,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4Zs github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -1609,6 +1603,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= diff --git a/weed/command/scaffold/filer.toml b/weed/command/scaffold/filer.toml index a685d50d8..a0e04e32c 100644 --- a/weed/command/scaffold/filer.toml +++ b/weed/command/scaffold/filer.toml @@ -186,6 +186,14 @@ hosts = [ ] username = "" password = "" +# Set the CA certificate path +ssl_ca_path = "" +# Set the client certificate path +ssl_cert_path = "" +# Set the client private key path +ssl_key_path = "" +# Check host name in the certificate +ssl_enable_host_verification = true # This changes the data layout. Only add new directories. Removing/Updating will cause data loss. superLargeDirectories = [] # Name of the datacenter local to this filer, used as host selection fallback. diff --git a/weed/filer/cassandra/cassandra_store.go b/weed/filer/cassandra/cassandra_store.go index 968a2b3c3..2ada62f78 100644 --- a/weed/filer/cassandra/cassandra_store.go +++ b/weed/filer/cassandra/cassandra_store.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - "github.com/gocql/gocql" + gocql "github.com/apache/cassandra-gocql-driver/v2" "github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/glog" diff --git a/weed/filer/cassandra/cassandra_store_kv.go b/weed/filer/cassandra/cassandra_store_kv.go index 49dc542de..a3023e163 100644 --- a/weed/filer/cassandra/cassandra_store_kv.go +++ b/weed/filer/cassandra/cassandra_store_kv.go @@ -5,7 +5,7 @@ import ( "encoding/base64" "fmt" - "github.com/gocql/gocql" + gocql "github.com/apache/cassandra-gocql-driver/v2" "github.com/seaweedfs/seaweedfs/weed/filer" ) diff --git a/weed/filer/cassandra2/cassandra_store.go b/weed/filer/cassandra2/cassandra_store.go index 7ce3d32c1..20f068f5c 100644 --- a/weed/filer/cassandra2/cassandra_store.go +++ b/weed/filer/cassandra2/cassandra_store.go @@ -4,9 +4,11 @@ import ( "context" "errors" "fmt" + "os" + "strings" "time" - "github.com/gocql/gocql" + gocql "github.com/apache/cassandra-gocql-driver/v2" "github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/glog" @@ -29,14 +31,23 @@ func (store *Cassandra2Store) GetName() string { } func (store *Cassandra2Store) Initialize(configuration util.Configuration, prefix string) (err error) { + enableHostVerification := true + if val := configuration.GetString(prefix + "ssl_enable_host_verification"); val != "" { + enableHostVerification = configuration.GetBool(prefix + "ssl_enable_host_verification") + } + return store.initialize( configuration.GetString(prefix+"keyspace"), configuration.GetStringSlice(prefix+"hosts"), configuration.GetString(prefix+"username"), configuration.GetString(prefix+"password"), + configuration.GetString(prefix+"ssl_ca_path"), + configuration.GetString(prefix+"ssl_cert_path"), + configuration.GetString(prefix+"ssl_key_path"), configuration.GetStringSlice(prefix+"superLargeDirectories"), configuration.GetString(prefix+"localDC"), configuration.GetInt(prefix+"connection_timeout_millisecond"), + enableHostVerification, ) } @@ -45,11 +56,50 @@ func (store *Cassandra2Store) isSuperLargeDirectory(dir string) (dirHash string, return } -func (store *Cassandra2Store) initialize(keyspace string, hosts []string, username string, password string, superLargeDirectories []string, localDC string, timeout int) (err error) { +func (store *Cassandra2Store) initialize(keyspace string, hosts []string, username string, password string, sslCaPath string, sslCertPath string, sslKeyPath string, superLargeDirectories []string, localDC string, timeout int, enableHostVerification bool) (err error) { store.cluster = gocql.NewCluster(hosts...) if username != "" && password != "" { store.cluster.Authenticator = gocql.PasswordAuthenticator{Username: username, Password: password} } + if sslCaPath != "" || sslCertPath != "" || sslKeyPath != "" { + if (sslCertPath != "" && sslKeyPath == "") || (sslCertPath == "" && sslKeyPath != "") { + return fmt.Errorf("both ssl_cert_path and ssl_key_path must be provided for mTLS, or neither") + } + + for _, path := range []string{sslCaPath, sslCertPath, sslKeyPath} { + if path != "" { + if _, err := os.Stat(path); err != nil { + return fmt.Errorf("ssl file %s not found: %v", path, err) + } + } + } + + store.cluster.SslOpts = &gocql.SslOptions{ + CaPath: sslCaPath, + CertPath: sslCertPath, + KeyPath: sslKeyPath, + EnableHostVerification: enableHostVerification, + } + + // check if port is already specified in hosts + hasPort := false + for _, host := range hosts { + if strings.Contains(host, ":") { + hasPort = true + break + } + } + if !hasPort { + // standard cassandra port is 9042, but AWS keyspaces uses 9142 + store.cluster.Port = 9142 + } + + if sslCertPath != "" { + glog.V(0).Infof("TLS enabled: mTLS with cert %s", sslCertPath) + } else { + glog.V(0).Infof("TLS enabled: server-verification with ca %s", sslCaPath) + } + } store.cluster.Keyspace = keyspace store.cluster.Timeout = time.Duration(timeout) * time.Millisecond glog.V(0).Infof("timeout = %d", timeout) diff --git a/weed/filer/cassandra2/cassandra_store_kv.go b/weed/filer/cassandra2/cassandra_store_kv.go index 3c1db7a45..31b351160 100644 --- a/weed/filer/cassandra2/cassandra_store_kv.go +++ b/weed/filer/cassandra2/cassandra_store_kv.go @@ -5,7 +5,7 @@ import ( "encoding/base64" "fmt" - "github.com/gocql/gocql" + gocql "github.com/apache/cassandra-gocql-driver/v2" "github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/util" )