diff --git a/server/embed/config_test.go b/server/embed/config_test.go index 9a24e5eb903..ba7af87abaa 100644 --- a/server/embed/config_test.go +++ b/server/embed/config_test.go @@ -94,22 +94,24 @@ func TestConfigFileOtherFields(t *testing.T) { func TestConfigFileFeatureGates(t *testing.T) { testCases := []struct { - name string - serverFeatureGatesJSON string - experimentalStopGRPCServiceOnDefrag string - experimentalInitialCorruptCheck string - experimentalCompactHashCheckEnabled string - experimentalTxnModeWriteWithSharedBuffer string - expectErr bool - expectedFeatures map[featuregate.Feature]bool + name string + serverFeatureGatesJSON string + experimentalStopGRPCServiceOnDefrag string + experimentalInitialCorruptCheck string + experimentalCompactHashCheckEnabled string + experimentalTxnModeWriteWithSharedBuffer string + experimentalPeerSkipClientSanVerification string + expectErr bool + expectedFeatures map[featuregate.Feature]bool }{ { name: "default", expectedFeatures: map[featuregate.Feature]bool{ - features.DistributedTracing: false, - features.StopGRPCServiceOnDefrag: false, - features.InitialCorruptCheck: false, - features.TxnModeWriteWithSharedBuffer: true, + features.DistributedTracing: false, + features.StopGRPCServiceOnDefrag: false, + features.InitialCorruptCheck: false, + features.TxnModeWriteWithSharedBuffer: true, + features.PeerSkipClientSanVerification: false, }, }, { @@ -130,6 +132,12 @@ func TestConfigFileFeatureGates(t *testing.T) { experimentalTxnModeWriteWithSharedBuffer: "false", expectErr: true, }, + { + name: "cannot set both experimental flag and feature gate flag for PeerSkipClientSanVerification", + serverFeatureGatesJSON: "PeerSkipClientSanVerification=true", + experimentalPeerSkipClientSanVerification: "false", + expectErr: true, + }, { name: "ok to set different experimental flag and feature gate flag", serverFeatureGatesJSON: "DistributedTracing=true", @@ -292,15 +300,49 @@ func TestConfigFileFeatureGates(t *testing.T) { features.CompactHashCheck: true, }, }, + { + name: "can set feature gate PeerSkipClientSanVerification to true from experimental flag", + experimentalPeerSkipClientSanVerification: "true", + expectedFeatures: map[featuregate.Feature]bool{ + features.PeerSkipClientSanVerification: true, + features.StopGRPCServiceOnDefrag: false, + features.DistributedTracing: false, + features.InitialCorruptCheck: false, + features.TxnModeWriteWithSharedBuffer: true, + }, + }, + { + name: "can set feature gate PeerSkipClientSanVerification to false from experimental flag", + experimentalPeerSkipClientSanVerification: "false", + expectedFeatures: map[featuregate.Feature]bool{ + features.PeerSkipClientSanVerification: false, + features.StopGRPCServiceOnDefrag: false, + features.DistributedTracing: false, + features.InitialCorruptCheck: false, + features.TxnModeWriteWithSharedBuffer: true, + }, + }, + { + name: "can set feature gate PeerSkipClientSanVerification through feature gates JSON", + serverFeatureGatesJSON: "PeerSkipClientSanVerification=true", + expectedFeatures: map[featuregate.Feature]bool{ + features.PeerSkipClientSanVerification: true, + features.StopGRPCServiceOnDefrag: false, + features.DistributedTracing: false, + features.InitialCorruptCheck: false, + features.TxnModeWriteWithSharedBuffer: true, + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { yc := struct { - ExperimentalStopGRPCServiceOnDefrag *bool `json:"experimental-stop-grpc-service-on-defrag,omitempty"` - ExperimentalInitialCorruptCheck *bool `json:"experimental-initial-corrupt-check,omitempty"` - ExperimentalCompactHashCheckEnabled *bool `json:"experimental-compact-hash-check-enabled,omitempty"` - ExperimentalTxnModeWriteWithSharedBuffer *bool `json:"experimental-txn-mode-write-with-shared-buffer,omitempty"` - ServerFeatureGatesJSON string `json:"feature-gates"` + ExperimentalStopGRPCServiceOnDefrag *bool `json:"experimental-stop-grpc-service-on-defrag,omitempty"` + ExperimentalInitialCorruptCheck *bool `json:"experimental-initial-corrupt-check,omitempty"` + ExperimentalCompactHashCheckEnabled *bool `json:"experimental-compact-hash-check-enabled,omitempty"` + ExperimentalTxnModeWriteWithSharedBuffer *bool `json:"experimental-txn-mode-write-with-shared-buffer,omitempty"` + ExperimentalPeerSkipClientSanVerification *bool `json:"experimental-peer-skip-client-san-verification,omitempty"` + ServerFeatureGatesJSON string `json:"feature-gates"` }{ ServerFeatureGatesJSON: tc.serverFeatureGatesJSON, } @@ -337,6 +379,14 @@ func TestConfigFileFeatureGates(t *testing.T) { yc.ExperimentalCompactHashCheckEnabled = &experimentalCompactHashCheckEnabled } + if tc.experimentalPeerSkipClientSanVerification != "" { + experimentalPeerSkipClientSanVerification, err := strconv.ParseBool(tc.experimentalPeerSkipClientSanVerification) + if err != nil { + t.Fatal(err) + } + yc.ExperimentalPeerSkipClientSanVerification = &experimentalPeerSkipClientSanVerification + } + b, err := yaml.Marshal(&yc) if err != nil { t.Fatal(err) diff --git a/server/embed/etcd.go b/server/embed/etcd.go index f5fa2c2c692..e5ff4eecee0 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -246,7 +246,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { } srvcfg.PeerTLSInfo.LocalAddr = srvcfg.ExperimentalLocalAddress - + srvcfg.PeerTLSInfo.SkipClientSANVerify = srvcfg.ServerFeatureGate.Enabled(features.PeerSkipClientSanVerification) print(e.cfg.logger, *cfg, srvcfg, memberInitialized) if e.Server, err = etcdserver.NewServer(srvcfg); err != nil { diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index 99cc279a1be..2798ca0a806 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -67,6 +67,7 @@ var ( "experimental-txn-mode-write-with-shared-buffer": "--experimental-txn-mode-write-with-shared-buffer is deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=TxnModeWriteWithSharedBuffer=true' instead.", "experimental-corrupt-check-time": "--experimental-corrupt-check-time is deprecated in v3.6 and will be decommissioned in v3.7. Use '--corrupt-check-time' instead.", "experimental-compaction-batch-limit": "--experimental-compaction-batch-limit is deprecated in v3.6 and will be decommissioned in v3.7. Use '--compaction-batch-limit' instead.", + "experimental-peer-skip-client-san-verification": "--experimental-peer-skip-client-san-verification is deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=PeerSkipClientSanVerification=true' instead.", } ) diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index 832716fb24f..fc5d9eedb20 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -292,7 +292,7 @@ Experimental feature: --compaction-batch-limit 1000 CompactionBatchLimit sets the maximum revisions deleted in each compaction batch. --experimental-peer-skip-client-san-verification 'false' - Skip verification of SAN field in client certificate for peer connections. + Skip verification of SAN field in client certificate for peer connections. Deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=PeerSkipClientSanVerification=true' instead. --experimental-watch-progress-notify-interval '10m' Duration of periodical watch progress notification. --experimental-warning-apply-duration '100ms' diff --git a/server/features/etcd_features.go b/server/features/etcd_features.go index 0a5d85ce28f..7ce5e489822 100644 --- a/server/features/etcd_features.go +++ b/server/features/etcd_features.go @@ -60,15 +60,21 @@ const ( // alpha: v3.6 // main PR: https://github.com/etcd-io/etcd/pull/14120 CompactHashCheck featuregate.Feature = "CompactHashCheck" + // PeerSkipClientSanVerification enables to skip the verification of Subject Alternative Name (SAN) field in client certificates during peer TLS communication + // owner: @wodeyoulai + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/14120 + PeerSkipClientSanVerification featuregate.Feature = "PeerSkipClientSanVerification" ) var ( DefaultEtcdServerFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ - DistributedTracing: {Default: false, PreRelease: featuregate.Alpha}, - StopGRPCServiceOnDefrag: {Default: false, PreRelease: featuregate.Alpha}, - InitialCorruptCheck: {Default: false, PreRelease: featuregate.Alpha}, - CompactHashCheck: {Default: false, PreRelease: featuregate.Alpha}, - TxnModeWriteWithSharedBuffer: {Default: true, PreRelease: featuregate.Beta}, + DistributedTracing: {Default: false, PreRelease: featuregate.Alpha}, + StopGRPCServiceOnDefrag: {Default: false, PreRelease: featuregate.Alpha}, + InitialCorruptCheck: {Default: false, PreRelease: featuregate.Alpha}, + CompactHashCheck: {Default: false, PreRelease: featuregate.Alpha}, + TxnModeWriteWithSharedBuffer: {Default: true, PreRelease: featuregate.Beta}, + PeerSkipClientSanVerification: {Default: false, PreRelease: featuregate.Alpha}, } // ExperimentalFlagToFeatureMap is the map from the cmd line flags of experimental features // to their corresponding feature gates. @@ -78,6 +84,7 @@ var ( "experimental-initial-corrupt-check": InitialCorruptCheck, "experimental-compact-hash-check-enabled": CompactHashCheck, "experimental-txn-mode-write-with-shared-buffer": TxnModeWriteWithSharedBuffer, + "experimental-peer-skip-client-san-verification": PeerSkipClientSanVerification, } )