filer.sync: support per-cluster mTLS with -a.security and -b.security (#8872)

* filer.sync: support per-cluster mTLS with -a.security and -b.security flags

When syncing between two clusters that use different certificate authorities,
a single security.toml cannot authenticate to both. Add -a.security and
-b.security flags so each filer can use its own security.toml for TLS.

Closes #8481

* security: fatal on failure to read explicitly provided security config

When -a.security or -b.security is specified, falling back to insecure
credentials on read error would silently bypass mTLS. Fatal instead.

* fix(filer.sync): use source filer's fromTsMs flag in initOffsetFromTsMs

A→B was using bFromTsMs and B→A was using aFromTsMs — these were
swapped. Each path should seed the target's offset with the source
filer's starting timestamp.

* security: return error from LoadClientTLSFromFile, resolve relative PEM paths

Change LoadClientTLSFromFile to return (grpc.DialOption, error) so
callers can handle failures explicitly instead of a silent insecure
fallback. Resolve relative PEM paths (grpc.ca, grpc.client.cert,
grpc.client.key) against the config file's directory.
This commit is contained in:
Chris Lu
2026-04-01 11:05:43 -07:00
committed by GitHub
parent 44d5cb8f90
commit 8572aae403
3 changed files with 61 additions and 14 deletions

View File

@@ -7,10 +7,13 @@ import (
"fmt"
"net"
"os"
"path/filepath"
"slices"
"strings"
"time"
"github.com/spf13/viper"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/util"
"google.golang.org/grpc"
@@ -139,6 +142,23 @@ func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption
return grpc.Creds(ta), nil
}
func LoadClientTLSFromFile(configFile string, component string) (grpc.DialOption, error) {
v := viper.New()
v.SetConfigFile(configFile)
if err := v.ReadInConfig(); err != nil {
return nil, fmt.Errorf("failed to read security config %s: %v", configFile, err)
}
// Resolve relative PEM paths against the config file's directory.
configDir := filepath.Dir(configFile)
for _, key := range []string{"grpc.ca", component + ".cert", component + ".key"} {
p := v.GetString(key)
if p != "" && !filepath.IsAbs(p) {
v.Set(key, filepath.Join(configDir, p))
}
}
return LoadClientTLS(&util.ViperProxy{Viper: v}, component), nil
}
func LoadClientTLS(config *util.ViperProxy, component string) grpc.DialOption {
if config == nil {
return grpc.WithTransportCredentials(insecure.NewCredentials())