Skip to content

Commit

Permalink
expose MinTLSVersion config for TLS handshake (#3103)
Browse files Browse the repository at this point in the history
* expose MinTLSVersion config

* address comment

* use valid TLS version in config test
  • Loading branch information
ZetaoZhuang authored Nov 12, 2024
1 parent 8e8a5fd commit 59a5022
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 8 deletions.
3 changes: 2 additions & 1 deletion cns/configuration/cns_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@
"MellanoxMonitorIntervalSecs": 30,
"AZRSettings": {
"PopulateHomeAzCacheRetryIntervalSecs": 60
}
},
"MinTLSVersion": "TLS 1.2"
}
5 changes: 5 additions & 0 deletions cns/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type CNSConfig struct {
WatchPods bool `json:"-"`
WireserverIP string
GRPCSettings GRPCSettings
MinTLSVersion string
}

type TelemetrySettings struct {
Expand Down Expand Up @@ -229,6 +230,10 @@ func SetCNSConfigDefaults(config *CNSConfig) {
if config.GRPCSettings.Port == 0 {
config.GRPCSettings.Port = 8080
}

if config.MinTLSVersion == "" {
config.MinTLSVersion = "TLS 1.2"
}
config.GRPCSettings.Enable = false
config.WatchPods = config.EnableIPAMv2 || config.EnableSwiftV2
}
Expand Down
10 changes: 7 additions & 3 deletions cns/configuration/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ func TestReadConfigFromFile(t *testing.T) {
AZRSettings: AZRSettings{
PopulateHomeAzCacheRetryIntervalSecs: 60,
},
UseHTTPS: true,
UseMTLS: true,
WireserverIP: "168.63.129.16",
UseHTTPS: true,
UseMTLS: true,
WireserverIP: "168.63.129.16",
MinTLSVersion: "TLS 1.3",
},
wantErr: false,
},
Expand Down Expand Up @@ -220,6 +221,7 @@ func TestSetCNSConfigDefaults(t *testing.T) {
IPAddress: "localhost",
Port: 8080,
},
MinTLSVersion: "TLS 1.2",
},
},
{
Expand Down Expand Up @@ -250,6 +252,7 @@ func TestSetCNSConfigDefaults(t *testing.T) {
IPAddress: "192.168.1.1",
Port: 9090,
},
MinTLSVersion: "TLS 1.3",
},
want: CNSConfig{
ChannelMode: "Other",
Expand Down Expand Up @@ -279,6 +282,7 @@ func TestSetCNSConfigDefaults(t *testing.T) {
IPAddress: "192.168.1.1",
Port: 9090,
},
MinTLSVersion: "TLS 1.3",
},
},
}
Expand Down
3 changes: 2 additions & 1 deletion cns/configuration/testdata/good.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@
"WireserverIP": "168.63.129.16",
"AZRSettings": {
"PopulateHomeAzCacheRetryIntervalSecs": 60
}
},
"MinTLSVersion": "TLS 1.3"
}
28 changes: 26 additions & 2 deletions cns/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const (
genericData = "com.microsoft.azure.network.generic"
)

var errTLSConfig = errors.New("unsupported TLS version name from config")

// Service defines Container Networking Service.
type Service struct {
*common.Service
Expand Down Expand Up @@ -179,10 +181,14 @@ func getTLSConfigFromFile(tlsSettings localtls.TlsSettings) (*tls.Config, error)
PrivateKey: privateKey,
Leaf: leafCertificate,
}
minTLSVersionNumber, err := parseTLSVersionName(tlsSettings.MinTLSVersion)
if err != nil {
return nil, errors.Wrap(err, "parsing MinTLSVersion from config")
}

tlsConfig := &tls.Config{
MaxVersion: tls.VersionTLS13,
MinVersion: tls.VersionTLS12,
MinVersion: minTLSVersionNumber,
Certificates: []tls.Certificate{
tlsCert,
},
Expand Down Expand Up @@ -226,8 +232,13 @@ func getTLSConfigFromKeyVault(tlsSettings localtls.TlsSettings, errChan chan<- e
errChan <- cr.Refresh(ctx, tlsSettings.KeyVaultCertificateRefreshInterval)
}()

minTLSVersionNumber, err := parseTLSVersionName(tlsSettings.MinTLSVersion)
if err != nil {
return nil, errors.Wrap(err, "parsing MinTLSVersion from config")
}

tlsConfig := tls.Config{
MinVersion: tls.VersionTLS12,
MinVersion: minTLSVersionNumber,
MaxVersion: tls.VersionTLS13,
GetCertificate: func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
return cr.GetCertificate(), nil
Expand Down Expand Up @@ -316,3 +327,16 @@ func (service *Service) SendErrorResponse(w http.ResponseWriter, errMsg error) {
err := acn.Encode(w, &resp)
logger.Errorf("[%s] %+v %s.", service.Name, &resp, err.Error())
}

// parseTLSVersionName returns the version number for the provided TLS version name
// (e.g. 0x0301)
func parseTLSVersionName(versionName string) (uint16, error) {
switch versionName {
case "TLS 1.2":
return tls.VersionTLS12, nil
case "TLS 1.3":
return tls.VersionTLS13, nil
default:
return 0, errors.Wrapf(errTLSConfig, "version name %s", versionName)
}
}
1 change: 1 addition & 0 deletions cns/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ func main() {
MSIResourceID: cnsconfig.MSISettings.ResourceID,
KeyVaultCertificateRefreshInterval: time.Duration(cnsconfig.KeyVaultSettings.RefreshIntervalInHrs) * time.Hour,
UseMTLS: cnsconfig.UseMTLS,
MinTLSVersion: cnsconfig.MinTLSVersion,
}
}

Expand Down
35 changes: 34 additions & 1 deletion cns/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func TestNewService(t *testing.T) {
TLSPort: "10091",
TLSSubjectName: "localhost",
TLSCertificatePath: testCertFilePath,
MinTLSVersion: "TLS 1.2",
}

svc, err := NewService(config.Name, config.Version, config.ChannelMode, config.Store)
Expand All @@ -94,10 +95,13 @@ func TestNewService(t *testing.T) {
err = svc.StartListener(config)
require.NoError(t, err)

minTLSVersionNumber, err := parseTLSVersionName(config.TLSSettings.MinTLSVersion)
require.NoError(t, err)

tlsClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
MinVersion: minTLSVersionNumber,
MaxVersion: tls.VersionTLS13,
ServerName: config.TLSSettings.TLSSubjectName,
// #nosec G402 for test purposes only
Expand Down Expand Up @@ -134,6 +138,7 @@ func TestNewService(t *testing.T) {
TLSSubjectName: "localhost",
TLSCertificatePath: testCertFilePath,
UseMTLS: true,
MinTLSVersion: "TLS 1.2",
}

svc, err := NewService(config.Name, config.Version, config.ChannelMode, config.Store)
Expand Down Expand Up @@ -322,3 +327,31 @@ func createTestCertificate(t *testing.T) string {

return testCertFilePath
}

func TestTLSVersionNumber(t *testing.T) {
t.Run("unsupported ServerSettings.MinTLSVersion TLS 1.0", func(t *testing.T) {
versionNumber, err := parseTLSVersionName("TLS 1.0")
require.Equal(t, uint16(0), versionNumber)
require.Error(t, err)
require.ErrorContains(t, err, "unsupported TLS version name")
})

t.Run("unsupported ServerSettings.MinTLSVersion TLS 1.1", func(t *testing.T) {
versionNumber, err := parseTLSVersionName("TLS 1.1")
require.Equal(t, uint16(0), versionNumber)
require.Error(t, err)
require.ErrorContains(t, err, "unsupported TLS version name")
})
t.Run("unsupported ServerSettings.MinTLSVersion TLS 1.4", func(t *testing.T) {
versionNumber, err := parseTLSVersionName("TLS 1.4")
require.Equal(t, uint16(0), versionNumber)
require.Error(t, err)
require.ErrorContains(t, err, "unsupported TLS version name")
})

t.Run("valid ServerSettings.MinTLSVersion", func(t *testing.T) {
versionNumber, err := parseTLSVersionName("TLS 1.2")
require.Equal(t, uint16(tls.VersionTLS12), versionNumber)
require.NoError(t, err)
})
}
1 change: 1 addition & 0 deletions server/tls/tlscertificate_retriever.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type TlsSettings struct {
MSIResourceID string
KeyVaultCertificateRefreshInterval time.Duration
UseMTLS bool
MinTLSVersion string
}

func GetTlsCertificateRetriever(settings TlsSettings) (TlsCertificateRetriever, error) {
Expand Down

0 comments on commit 59a5022

Please sign in to comment.