feat: use RSA key for kube-apiserver service account key

Fixes #8111

Starting with 1.7, use RSA instead of ECDSA.

RSA is way slower, but it has better support with other providers.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
Andrey Smirnov 2024-01-31 16:49:59 +04:00
parent a5e13c696d
commit 7af48bd559
No known key found for this signature in database
GPG Key ID: FE042E3D4085A811
4 changed files with 86 additions and 6 deletions

View File

@ -49,6 +49,12 @@ machine:
features:
localDNS: false
```
"""
[notes.rsa-service-account]
title = "Kubernetes API Server Service Account Key"
description = """\
Talos Linux starting from this release uses RSA key for Kubernetes API Server Service Account instead of ECDSA key to provide better compatibility with external OpenID Connect implementations.
"""
[make_deps]

View File

@ -24,6 +24,7 @@ type VersionContract struct {
// Well-known Talos version contracts.
var (
TalosVersionCurrent = (*VersionContract)(nil)
TalosVersion1_7 = &VersionContract{1, 7}
TalosVersion1_6 = &VersionContract{1, 6}
TalosVersion1_5 = &VersionContract{1, 5}
TalosVersion1_4 = &VersionContract{1, 4}
@ -184,3 +185,8 @@ func (contract *VersionContract) KubePrismEnabled() bool {
func (contract *VersionContract) LocalDNSEnabled() bool {
return contract.Greater(TalosVersion1_6)
}
// UseRSAServiceAccountKey returns true if version of Talos should use RSA Service Account key for the kube-apiserver.
func (contract *VersionContract) UseRSAServiceAccountKey() bool {
return contract.Greater(TalosVersion1_6)
}

View File

@ -67,6 +67,35 @@ func TestContractCurrent(t *testing.T) {
assert.True(t, contract.SecretboxEncryptionSupported())
assert.True(t, contract.DiskQuotaSupportEnabled())
assert.True(t, contract.KubePrismEnabled())
assert.True(t, contract.LocalDNSEnabled())
assert.True(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_7(t *testing.T) {
contract := config.TalosVersion1_7
assert.True(t, contract.SupportsAggregatorCA())
assert.True(t, contract.SupportsECDSAKeys())
assert.True(t, contract.SupportsServiceAccount())
assert.True(t, contract.SupportsRBACFeature())
assert.True(t, contract.SupportsDynamicCertSANs())
assert.True(t, contract.SupportsECDSASHA256())
assert.True(t, contract.ClusterDiscoveryEnabled())
assert.False(t, contract.PodSecurityPolicyEnabled())
assert.True(t, contract.PodSecurityAdmissionEnabled())
assert.True(t, contract.StableHostnameEnabled())
assert.True(t, contract.KubeletDefaultRuntimeSeccompProfileEnabled())
assert.False(t, contract.KubernetesAlternateImageRegistries())
assert.True(t, contract.KubernetesAllowSchedulingOnControlPlanes())
assert.True(t, contract.KubernetesDiscoveryBackendDisabled())
assert.True(t, contract.ApidExtKeyUsageCheckEnabled())
assert.True(t, contract.APIServerAuditPolicySupported())
assert.True(t, contract.KubeletManifestsDirectoryDisabled())
assert.True(t, contract.SecretboxEncryptionSupported())
assert.True(t, contract.DiskQuotaSupportEnabled())
assert.True(t, contract.KubePrismEnabled())
assert.True(t, contract.LocalDNSEnabled())
assert.True(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_6(t *testing.T) {
@ -92,6 +121,8 @@ func TestContract1_6(t *testing.T) {
assert.True(t, contract.SecretboxEncryptionSupported())
assert.True(t, contract.DiskQuotaSupportEnabled())
assert.True(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_5(t *testing.T) {
@ -117,6 +148,8 @@ func TestContract1_5(t *testing.T) {
assert.True(t, contract.SecretboxEncryptionSupported())
assert.True(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_4(t *testing.T) {
@ -142,6 +175,8 @@ func TestContract1_4(t *testing.T) {
assert.True(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_3(t *testing.T) {
@ -167,6 +202,8 @@ func TestContract1_3(t *testing.T) {
assert.True(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_2(t *testing.T) {
@ -192,6 +229,8 @@ func TestContract1_2(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_1(t *testing.T) {
@ -217,6 +256,8 @@ func TestContract1_1(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract1_0(t *testing.T) {
@ -242,6 +283,8 @@ func TestContract1_0(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_14(t *testing.T) {
@ -267,6 +310,8 @@ func TestContract0_14(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_13(t *testing.T) {
@ -292,6 +337,8 @@ func TestContract0_13(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_12(t *testing.T) {
@ -317,6 +364,8 @@ func TestContract0_12(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_11(t *testing.T) {
@ -342,6 +391,8 @@ func TestContract0_11(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_10(t *testing.T) {
@ -367,6 +418,8 @@ func TestContract0_10(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_9(t *testing.T) {
@ -392,6 +445,8 @@ func TestContract0_9(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}
func TestContract0_8(t *testing.T) {
@ -417,4 +472,6 @@ func TestContract0_8(t *testing.T) {
assert.False(t, contract.SecretboxEncryptionSupported())
assert.False(t, contract.DiskQuotaSupportEnabled())
assert.False(t, contract.KubePrismEnabled())
assert.False(t, contract.LocalDNSEnabled())
assert.False(t, contract.UseRSAServiceAccountKey())
}

View File

@ -252,13 +252,24 @@ func (bundle *Bundle) populate(versionContract *config.VersionContract) error {
}
if versionContract.SupportsServiceAccount() && bundle.Certs.K8sServiceAccount == nil {
serviceAccount, err := x509.NewECDSAKey()
if err != nil {
return err
}
if versionContract.UseRSAServiceAccountKey() {
serviceAccount, err := x509.NewRSAKey()
if err != nil {
return err
}
bundle.Certs.K8sServiceAccount = &x509.PEMEncodedKey{
Key: serviceAccount.KeyPEM,
bundle.Certs.K8sServiceAccount = &x509.PEMEncodedKey{
Key: serviceAccount.KeyPEM,
}
} else {
serviceAccount, err := x509.NewECDSAKey()
if err != nil {
return err
}
bundle.Certs.K8sServiceAccount = &x509.PEMEncodedKey{
Key: serviceAccount.KeyPEM,
}
}
}