From 5d0dbefd752e0dbef3787e92da5a058827fd914c Mon Sep 17 00:00:00 2001 From: Alex Rodriguez <131964409+ezekiel-alexrod@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:24:26 +0000 Subject: [PATCH 1/2] salt: add x509 extensions to CA and leaf certificates (RFC 5280) Add `subjectKeyIdentifier` (SKI) to all 6 CA certificates and `authorityKeyIdentifier` (AKI) to all leaf certificates via the 8 x509 signing policies, per RFC 5280: - SKI on CA certs: MUST (Section 4.2.1.2) - AKI on leaf certs: MUST (Section 4.2.1.1) - AKI on self-signed CAs: MAY be omitted (Section 4.2.1.1) The AKI keyid in leaf certs references the SKI of the issuing CA, establishing the chain of trust identifier required by the RFC. On upgrade, Salt detects the missing extensions and re-issues the certificates while preserving the existing private keys. Closes: MK8S-201 --- CHANGELOG.md | 4 ++++ pillar/metalk8s/roles/ca.sls | 8 ++++++++ salt/metalk8s/addons/dex/ca/installed.sls | 1 + salt/metalk8s/addons/nginx-ingress/ca/installed.sls | 1 + salt/metalk8s/backup/certs/ca.sls | 1 + salt/metalk8s/kubernetes/ca/etcd/installed.sls | 1 + salt/metalk8s/kubernetes/ca/front-proxy/installed.sls | 1 + salt/metalk8s/kubernetes/ca/kubernetes/installed.sls | 1 + salt/tests/unit/formulas/data/base_pillar.yaml | 7 +++++++ 9 files changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1345cbb57a..2cadd392be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,10 @@ - Implement ability to add certificates to fluent-bit by mounting a fluent-bit-certs secret (PR[#4812](https://github.com/scality/metalk8s/pull/4812)) +- Add x509 `subjectKeyIdentifier` extension to CA certificates and + `authorityKeyIdentifier` extension to leaf certificates per RFC 5280 + (PR[#4836](https://github.com/scality/metalk8s/pull/4836)) + ### Bug Fixes - Fix a bug where part of the upgrade process would silently be skipped diff --git a/pillar/metalk8s/roles/ca.sls b/pillar/metalk8s/roles/ca.sls index 6fdb610b92..bb17740ada 100644 --- a/pillar/metalk8s/roles/ca.sls +++ b/pillar/metalk8s/roles/ca.sls @@ -34,45 +34,53 @@ x509_signing_policies: - signing_cert: /etc/kubernetes/pki/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: clientAuth + - authorityKeyIdentifier: keyid kube_apiserver_server_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/ca.key - signing_cert: /etc/kubernetes/pki/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid etcd_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/etcd/ca.key - signing_cert: /etc/kubernetes/pki/etcd/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: clientAuth + - authorityKeyIdentifier: keyid etcd_server_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/etcd/ca.key - signing_cert: /etc/kubernetes/pki/etcd/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth, clientAuth + - authorityKeyIdentifier: keyid front_proxy_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/front-proxy-ca.key - signing_cert: /etc/kubernetes/pki/front-proxy-ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: clientAuth + - authorityKeyIdentifier: keyid ingress_server_policy: - minions: '*' - signing_private_key: /etc/metalk8s/pki/nginx-ingress/ca.key - signing_cert: /etc/metalk8s/pki/nginx-ingress/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid dex_server_policy: - minions: '*' - signing_private_key: /etc/metalk8s/pki/dex/ca.key - signing_cert: /etc/metalk8s/pki/dex/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid backup_server_policy: - minions: '*' - signing_private_key: /etc/metalk8s/pki/backup-server/ca.key - signing_cert: /etc/metalk8s/pki/backup-server/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid diff --git a/salt/metalk8s/addons/dex/ca/installed.sls b/salt/metalk8s/addons/dex/ca/installed.sls index 7266166673..25b1b5dd54 100644 --- a/salt/metalk8s/addons/dex/ca/installed.sls +++ b/salt/metalk8s/addons/dex/ca/installed.sls @@ -27,6 +27,7 @@ Generate dex CA certificate: - CN: dex-ca - keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign" - basicConstraints: "critical CA:true" + - subjectKeyIdentifier: hash - days_valid: {{ dex.ca.cert.days_valid }} - user: root - group: root diff --git a/salt/metalk8s/addons/nginx-ingress/ca/installed.sls b/salt/metalk8s/addons/nginx-ingress/ca/installed.sls index fe96e8b651..ed9395df42 100644 --- a/salt/metalk8s/addons/nginx-ingress/ca/installed.sls +++ b/salt/metalk8s/addons/nginx-ingress/ca/installed.sls @@ -27,6 +27,7 @@ Generate Ingress CA certificate: - CN: ingress-ca - keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign" - basicConstraints: "critical CA:true" + - subjectKeyIdentifier: hash - days_valid: {{ nginx_ingress.ca.cert.days_valid }} - user: root - group: root diff --git a/salt/metalk8s/backup/certs/ca.sls b/salt/metalk8s/backup/certs/ca.sls index e36737bb71..b9fc97efce 100644 --- a/salt/metalk8s/backup/certs/ca.sls +++ b/salt/metalk8s/backup/certs/ca.sls @@ -27,6 +27,7 @@ Generate backup server CA certificate: - CN: backup-server-ca - keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign" - basicConstraints: "critical CA:true" + - subjectKeyIdentifier: hash - days_valid: {{ backup_server.ca.cert.days_valid }} - user: root - group: root diff --git a/salt/metalk8s/kubernetes/ca/etcd/installed.sls b/salt/metalk8s/kubernetes/ca/etcd/installed.sls index a8401c1779..14a50618c9 100644 --- a/salt/metalk8s/kubernetes/ca/etcd/installed.sls +++ b/salt/metalk8s/kubernetes/ca/etcd/installed.sls @@ -27,6 +27,7 @@ Generate etcd CA certificate: - CN: etcd-ca - keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign" - basicConstraints: "critical CA:true" + - subjectKeyIdentifier: hash - days_valid: {{ etcd.ca.cert.days_valid }} - user: root - group: root diff --git a/salt/metalk8s/kubernetes/ca/front-proxy/installed.sls b/salt/metalk8s/kubernetes/ca/front-proxy/installed.sls index a0934efde5..f7504cd266 100644 --- a/salt/metalk8s/kubernetes/ca/front-proxy/installed.sls +++ b/salt/metalk8s/kubernetes/ca/front-proxy/installed.sls @@ -27,6 +27,7 @@ Generate front proxy CA certificate: - CN: front-proxy-ca - keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign" - basicConstraints: "critical CA:true" + - subjectKeyIdentifier: hash - days_valid: {{ front_proxy.ca.cert.days_valid }} - user: root - group: root diff --git a/salt/metalk8s/kubernetes/ca/kubernetes/installed.sls b/salt/metalk8s/kubernetes/ca/kubernetes/installed.sls index 122d65b0ab..ade9647554 100644 --- a/salt/metalk8s/kubernetes/ca/kubernetes/installed.sls +++ b/salt/metalk8s/kubernetes/ca/kubernetes/installed.sls @@ -27,6 +27,7 @@ Generate CA certificate: - CN: kubernetes - keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign" - basicConstraints: "critical CA:true" + - subjectKeyIdentifier: hash - days_valid: {{ ca.cert.days_valid }} - user: root - group: root diff --git a/salt/tests/unit/formulas/data/base_pillar.yaml b/salt/tests/unit/formulas/data/base_pillar.yaml index 1e402c9a6b..430a4c3721 100644 --- a/salt/tests/unit/formulas/data/base_pillar.yaml +++ b/salt/tests/unit/formulas/data/base_pillar.yaml @@ -93,42 +93,49 @@ x509_signing_policies: - signing_cert: /etc/metalk8s/pki/dex/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid etcd_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/etcd/ca.key - signing_cert: /etc/kubernetes/pki/etcd/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: clientAuth + - authorityKeyIdentifier: keyid etcd_server_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/etcd/ca.key - signing_cert: /etc/kubernetes/pki/etcd/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth, clientAuth + - authorityKeyIdentifier: keyid front_proxy_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/front-proxy-ca.key - signing_cert: /etc/kubernetes/pki/front-proxy-ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: clientAuth + - authorityKeyIdentifier: keyid ingress_server_policy: - minions: '*' - signing_private_key: /etc/metalk8s/pki/nginx-ingress/ca.key - signing_cert: /etc/metalk8s/pki/nginx-ingress/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid kube_apiserver_client_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/ca.key - signing_cert: /etc/kubernetes/pki/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: clientAuth + - authorityKeyIdentifier: keyid kube_apiserver_server_policy: - minions: '*' - signing_private_key: /etc/kubernetes/pki/ca.key - signing_cert: /etc/kubernetes/pki/ca.crt - keyUsage: critical digitalSignature, keyEncipherment - extendedKeyUsage: serverAuth + - authorityKeyIdentifier: keyid certificates: client: files: From 9f38ed757cab8af122378e8585b492bd7654dff0 Mon Sep 17 00:00:00 2001 From: Alex Rodriguez <131964409+ezekiel-alexrod@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:21:39 +0000 Subject: [PATCH 2/2] salt: add authorityKeyIdentifier to leaf cert states Add `authorityKeyIdentifier: keyid` to all 13 leaf certificate `x509.certificate_managed` states so that Salt detects the missing extension on existing certs and re-issues them during upgrade. The signing policies alone (in pillar) control what extensions are stamped on new certs, but Salt does not compare signing policy extensions against existing certs. Adding the extension in the state itself triggers the diff detection needed for upgrade. Closes: MK8S-201 --- salt/metalk8s/addons/dex/certs/server.sls | 1 + .../metalk8s/addons/nginx-ingress-control-plane/certs/server.sls | 1 + salt/metalk8s/addons/nginx-ingress/certs/server.sls | 1 + salt/metalk8s/backup/certs/server.sls | 1 + salt/metalk8s/kubernetes/apiserver/certs/etcd-client.sls | 1 + salt/metalk8s/kubernetes/apiserver/certs/front-proxy-client.sls | 1 + salt/metalk8s/kubernetes/apiserver/certs/kubelet-client.sls | 1 + salt/metalk8s/kubernetes/apiserver/certs/server.sls | 1 + salt/metalk8s/kubernetes/etcd/certs/healthcheck-client.sls | 1 + salt/metalk8s/kubernetes/etcd/certs/peer.sls | 1 + salt/metalk8s/kubernetes/etcd/certs/server.sls | 1 + salt/metalk8s/salt/master/certs/etcd-client.sls | 1 + salt/metalk8s/salt/master/certs/salt-api.sls | 1 + 13 files changed, 13 insertions(+) diff --git a/salt/metalk8s/addons/dex/certs/server.sls b/salt/metalk8s/addons/dex/certs/server.sls index 027c8f1ba5..73c716ff99 100644 --- a/salt/metalk8s/addons/dex/certs/server.sls +++ b/salt/metalk8s/addons/dex/certs/server.sls @@ -45,6 +45,7 @@ Generate Dex server certificate: - signing_policy: {{ dex.cert.server_signing_policy }} - CN: dex-server - subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files.dex.days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/addons/nginx-ingress-control-plane/certs/server.sls b/salt/metalk8s/addons/nginx-ingress-control-plane/certs/server.sls index a8d588b68a..84da43e5d0 100644 --- a/salt/metalk8s/addons/nginx-ingress-control-plane/certs/server.sls +++ b/salt/metalk8s/addons/nginx-ingress-control-plane/certs/server.sls @@ -45,6 +45,7 @@ Generate Control-Plane Ingress server certificate: - signing_policy: {{ nginx_ingress.cert.server_signing_policy }} - CN: nginx-ingress-control-plane-server - subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files['control-plane-ingress'].days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/addons/nginx-ingress/certs/server.sls b/salt/metalk8s/addons/nginx-ingress/certs/server.sls index 5c8a28f32a..1e17ed6460 100644 --- a/salt/metalk8s/addons/nginx-ingress/certs/server.sls +++ b/salt/metalk8s/addons/nginx-ingress/certs/server.sls @@ -41,6 +41,7 @@ Generate Workload-Plane Ingress server certificate: - signing_policy: {{ nginx_ingress.cert.server_signing_policy }} - CN: nginx-ingress-workload-plane-server - subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files['workload-plane-ingress'].days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/backup/certs/server.sls b/salt/metalk8s/backup/certs/server.sls index b411190992..d3e3a36adc 100644 --- a/salt/metalk8s/backup/certs/server.sls +++ b/salt/metalk8s/backup/certs/server.sls @@ -35,6 +35,7 @@ Generate backup server certificate: - signing_policy: {{ backup_server.cert.server_signing_policy }} - CN: backup - subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files["backup-server"].days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/kubernetes/apiserver/certs/etcd-client.sls b/salt/metalk8s/kubernetes/apiserver/certs/etcd-client.sls index efe90fc29c..bdeb528f08 100644 --- a/salt/metalk8s/kubernetes/apiserver/certs/etcd-client.sls +++ b/salt/metalk8s/kubernetes/apiserver/certs/etcd-client.sls @@ -29,6 +29,7 @@ Generate apiserver etcd client certificate: - signing_policy: {{ etcd.cert.apiserver_client_signing_policy }} - CN: kube-apiserver-etcd-client - O: "system:masters" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.client.files['apiserver-etcd'].days_valid | default(certificates.client.days_valid) }} diff --git a/salt/metalk8s/kubernetes/apiserver/certs/front-proxy-client.sls b/salt/metalk8s/kubernetes/apiserver/certs/front-proxy-client.sls index 7ad58b1a68..3144f55c3f 100644 --- a/salt/metalk8s/kubernetes/apiserver/certs/front-proxy-client.sls +++ b/salt/metalk8s/kubernetes/apiserver/certs/front-proxy-client.sls @@ -28,6 +28,7 @@ Generate front proxy client certificate: - ca_server: {{ pillar['metalk8s']['ca']['minion'] }} - signing_policy: {{ front_proxy.cert.client_signing_policy }} - CN: front-proxy-client + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.client.files['front-proxy'].days_valid | default(certificates.client.days_valid) }} diff --git a/salt/metalk8s/kubernetes/apiserver/certs/kubelet-client.sls b/salt/metalk8s/kubernetes/apiserver/certs/kubelet-client.sls index d0ce6febf8..dd46a2763e 100644 --- a/salt/metalk8s/kubernetes/apiserver/certs/kubelet-client.sls +++ b/salt/metalk8s/kubernetes/apiserver/certs/kubelet-client.sls @@ -29,6 +29,7 @@ Generate kube-apiserver kubelet client certificate: - signing_policy: {{ kube_api.cert.client_signing_policy }} - CN: kube-apiserver-kubelet-client - O: "system:masters" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.client.files['apiserver-kubelet'].days_valid | default(certificates.client.days_valid) }} diff --git a/salt/metalk8s/kubernetes/apiserver/certs/server.sls b/salt/metalk8s/kubernetes/apiserver/certs/server.sls index 64c4813d54..1340944f18 100644 --- a/salt/metalk8s/kubernetes/apiserver/certs/server.sls +++ b/salt/metalk8s/kubernetes/apiserver/certs/server.sls @@ -43,6 +43,7 @@ Generate kube-apiserver certificate: - signing_policy: {{ kube_api.cert.server_signing_policy }} - CN: kube-apiserver - subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files.apiserver.days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/kubernetes/etcd/certs/healthcheck-client.sls b/salt/metalk8s/kubernetes/etcd/certs/healthcheck-client.sls index 7f82c8bf96..cb287b6192 100644 --- a/salt/metalk8s/kubernetes/etcd/certs/healthcheck-client.sls +++ b/salt/metalk8s/kubernetes/etcd/certs/healthcheck-client.sls @@ -29,6 +29,7 @@ Generate etcd healthcheck client certificate: - signing_policy: {{ etcd.cert.healthcheck_client_signing_policy }} - CN: kube-etcd-healthcheck-client - O: "system:masters" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.client.files['etcd-healthcheck'].days_valid | default(certificates.client.days_valid) }} diff --git a/salt/metalk8s/kubernetes/etcd/certs/peer.sls b/salt/metalk8s/kubernetes/etcd/certs/peer.sls index 3fab1ff01f..a75e270456 100644 --- a/salt/metalk8s/kubernetes/etcd/certs/peer.sls +++ b/salt/metalk8s/kubernetes/etcd/certs/peer.sls @@ -29,6 +29,7 @@ Generate etcd peer certificate: - signing_policy: {{ etcd.cert.peer_signing_policy }} - CN: "{{ grains['fqdn'] }}" - subjectAltName: "DNS:{{ grains['fqdn'] }}, DNS:localhost, IP:{{ grains['metalk8s']['control_plane_ip'] }}, IP:127.0.0.1" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files['etcd-peer'].days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/kubernetes/etcd/certs/server.sls b/salt/metalk8s/kubernetes/etcd/certs/server.sls index e439816adc..326b323af3 100644 --- a/salt/metalk8s/kubernetes/etcd/certs/server.sls +++ b/salt/metalk8s/kubernetes/etcd/certs/server.sls @@ -29,6 +29,7 @@ Generate etcd server certificate: - signing_policy: {{ etcd.cert.server_signing_policy }} - CN: "{{ grains['fqdn'] }}" - subjectAltName: "DNS:{{ grains['fqdn'] }}, DNS:localhost, IP:{{ grains['metalk8s']['control_plane_ip'] }}, IP:127.0.0.1" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files.etcd.days_valid | default(certificates.server.days_valid) }} diff --git a/salt/metalk8s/salt/master/certs/etcd-client.sls b/salt/metalk8s/salt/master/certs/etcd-client.sls index 9eb960e8a5..472f6a21ab 100644 --- a/salt/metalk8s/salt/master/certs/etcd-client.sls +++ b/salt/metalk8s/salt/master/certs/etcd-client.sls @@ -28,6 +28,7 @@ Generate salt master etcd client certificate: - ca_server: {{ pillar['metalk8s']['ca']['minion'] }} - signing_policy: {{ etcd.cert.apiserver_client_signing_policy }} - CN: etcd-salt-master-client + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.client.files['salt-master-etcd'].days_valid | default(certificates.client.days_valid) }} diff --git a/salt/metalk8s/salt/master/certs/salt-api.sls b/salt/metalk8s/salt/master/certs/salt-api.sls index 60c77a0753..208563ce01 100644 --- a/salt/metalk8s/salt/master/certs/salt-api.sls +++ b/salt/metalk8s/salt/master/certs/salt-api.sls @@ -42,6 +42,7 @@ Generate Salt API certificate: - signing_policy: {{ kube_api.cert.server_signing_policy }} - CN: salt-api on {{ grains.id }} - subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}" + - authorityKeyIdentifier: keyid - days_valid: {{ certificates.server.files['salt-api'].days_valid | default(certificates.server.days_valid) }}