Skip to content

Commit b1f4fb6

Browse files
authored
Add admission config to apiserver (#994)
* Add admission config to apiserver * Add CA cert injection * Fix error message * Move helm value * Fix key * Disable by default
1 parent 8b1e958 commit b1f4fb6

File tree

6 files changed

+116
-2
lines changed

6 files changed

+116
-2
lines changed

charts/kube-master/templates/api.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ spec:
6666
path: aggregation-aggregator.pem
6767
- key: aggregation-aggregator-key.pem
6868
path: aggregation-aggregator-key.pem
69+
{{- if .Values.api.admissionConfig.enabled }}
70+
- key: admission.pem
71+
path: admission.pem
72+
- key: admission-key.pem
73+
path: admission-key.pem
74+
{{- end }}
6975
{{- if .Values.api.sniCertSecret }}
7076
- name: sni-certs
7177
secret:
@@ -125,6 +131,16 @@ spec:
125131
- name: logs
126132
emptyDir: {}
127133
{{- end }}
134+
{{- if .Values.api.admissionConfig.enabled }}
135+
- name: admission-config
136+
configMap:
137+
name: {{ include "master.fullname" . }}
138+
items:
139+
- key: admission.yaml
140+
path: config.yaml
141+
- key: admission-kubeconfig
142+
path: kubeconfig
143+
{{- end }}
128144
initContainers:
129145
- name: etcd-wait
130146
image: "{{ include "etcd.image" . }}"
@@ -269,6 +285,9 @@ spec:
269285
- --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
270286
{{- else }}
271287
- --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
288+
{{- end }}
289+
{{- if .Values.api.admissionConfig.enabled }}
290+
- --admission-control-config-file=/etc/kubernetes/admission/config.yaml
272291
{{- end }}
273292
volumeMounts:
274293
- mountPath: /etc/kubernetes/certs
@@ -295,6 +314,11 @@ spec:
295314
- mountPath: /var/log
296315
name: logs
297316
{{- end}}
317+
{{- if .Values.api.admissionConfig.enabled }}
318+
- mountPath: /etc/kubernetes/admission
319+
name: admission-config
320+
readOnly: true
321+
{{- end }}
298322
livenessProbe:
299323
{{- if .Values.etcd.backup.enabled }}
300324
exec:

charts/kube-master/templates/configmap.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,27 @@ data:
255255
restartPolicy: Never
256256
serviceAccountName: default
257257
terminationGracePeriodSeconds: 30
258+
{{- if .Values.api.admissionConfig.enabled }}
259+
admission.yaml: |-
260+
apiVersion: apiserver.config.k8s.io/v1
261+
kind: AdmissionConfiguration
262+
plugins:
263+
- name: ValidatingAdmissionWebhook
264+
configuration:
265+
apiVersion: apiserver.config.k8s.io/v1
266+
kind: WebhookAdmissionConfiguration
267+
kubeConfigFile: "/etc/kubernetes/admission/kubeconfig"
268+
- name: MutatingAdmissionWebhook
269+
configuration:
270+
apiVersion: apiserver.config.k8s.io/v1
271+
kind: WebhookAdmissionConfiguration
272+
kubeConfigFile: "/etc/kubernetes/admission/kubeconfig"
273+
admission-kubeconfig: |-
274+
apiVersion: v1
275+
kind: Config
276+
users:
277+
- name: '*'
278+
user:
279+
client-certificate: /etc/kubernetes/certs/admission.pem
280+
client-key: /etc/kubernetes/certs/admission-key.pem
281+
{{- end }}

charts/kube-master/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ api:
5656
limits:
5757
cpu: 1
5858
memory: 2Gi
59+
admissionConfig:
60+
enabled: false
5961

6062
cloudControllerManager:
6163
replicaCount: 1

pkg/apis/kubernikus/v1/secret.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ type Certificates struct {
126126
AggregationCACertificate string `json:"aggregation-ca.pem"`
127127
AggregationAggregatorPrivateKey string `json:"aggregation-aggregator-key.pem"`
128128
AggregationAggregatorCertificate string `json:"aggregation-aggregator.pem"`
129+
130+
AdmissionCAPrivateKey string `json:"admission-ca-key.pem"`
131+
AdmissionCACertificate string `json:"admission-ca.pem"`
132+
AdmissionPrivateKey string `json:"admission-key.pem"`
133+
AdmissionCertificate string `json:"admission.pem"`
129134
}
130135

131136
func (s *Certificates) ToStringData() (map[string]string, error) {

pkg/controller/ground/reconciler.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"helm.sh/helm/v3/pkg/chartutil"
1515
"helm.sh/helm/v3/pkg/engine"
1616
"helm.sh/helm/v3/pkg/releaseutil"
17+
corev1 "k8s.io/api/core/v1"
1718
extensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1819
"k8s.io/apimachinery/pkg/api/errors"
1920
"k8s.io/apimachinery/pkg/api/meta"
@@ -32,6 +33,7 @@ import (
3233
v1 "github.com/sapcc/kubernikus/pkg/apis/kubernikus/v1"
3334
"github.com/sapcc/kubernikus/pkg/client/openstack/project"
3435
"github.com/sapcc/kubernikus/pkg/controller/config"
36+
"github.com/sapcc/kubernikus/pkg/util"
3537
)
3638

3739
const SeedChartPath string = "charts/seed"
@@ -40,6 +42,7 @@ const ManagedByLabelKey string = "cloud.sap/managed-by"
4042
const ManagedByLabelValue string = "kubernikus"
4143
const SkipPatchKey string = "kubernikus.cloud.sap/skip-manage"
4244
const SkipPatchValue string = "true"
45+
const InjectAdmissionCAKey string = "kubernikus.cloud.sap/inject-admission-ca"
4346

4447
var recreateKinds map[string]struct{} = map[string]struct{}{
4548
"RoleBinding": {},
@@ -206,6 +209,49 @@ func (sr *SeedReconciler) ReconcileSeeding(chartPath string, values map[string]i
206209
if err != nil {
207210
return err
208211
}
212+
213+
// inject admission CA in labeled namespaces
214+
k8sClient, err := sr.Clients.Satellites.ClientFor(sr.Kluster)
215+
if err != nil {
216+
return err
217+
}
218+
nsList, err := k8sClient.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=true", InjectAdmissionCAKey)})
219+
if err != nil {
220+
return err
221+
}
222+
if nsList.Size() > 0 {
223+
secret, err := util.KlusterSecret(sr.Clients.Kubernetes, sr.Kluster)
224+
if err != nil {
225+
return fmt.Errorf("Couldn't get kluster secret: %s", err)
226+
}
227+
ca := map[string]string{"ca.crt": secret.Certificates.AdmissionCACertificate}
228+
cm := corev1.ConfigMap{
229+
TypeMeta: metav1.TypeMeta{
230+
Kind: "ConfigMap",
231+
APIVersion: "v1",
232+
},
233+
ObjectMeta: metav1.ObjectMeta{
234+
Name: "admission-auth-ca",
235+
},
236+
Data: ca,
237+
}
238+
for _, ns := range nsList.Items {
239+
_, err = k8sClient.CoreV1().ConfigMaps(ns.Name).Create(context.TODO(), &cm, metav1.CreateOptions{})
240+
if errors.IsAlreadyExists(err) {
241+
_, err = k8sClient.CoreV1().ConfigMaps(ns.Name).Update(context.TODO(), &cm, metav1.UpdateOptions{})
242+
}
243+
if err != nil {
244+
return fmt.Errorf("Admission CA certificate reconciliation in namespace %s failed: %s", ns.Name, err)
245+
}
246+
sr.Logger.Log(
247+
"msg", "Reconciling admission CA certificate",
248+
"namespace", ns.Name,
249+
"kluster", sr.Kluster.GetName(),
250+
"project", sr.Kluster.Account(),
251+
"v", 6)
252+
}
253+
}
254+
209255
sr.Logger.Log(
210256
"msg", "Seed reconciliation: successful",
211257
"kluster", sr.Kluster.GetName(),

pkg/util/certificates.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import (
2525
)
2626

2727
const (
28-
//by default we generate certs with 2 year validity
29-
defaultCertValidity = 2 * time.Hour * 24 * 365
28+
//by default we generate certs with 1 year validity
29+
defaultCertValidity = 1 * time.Hour * 24 * 365
3030
//out CAs are valid for 10 years
3131
caValidity = 10 * time.Hour * 24 * 365
3232
// renew certs 90 days before they expire
@@ -180,6 +180,10 @@ func (cf *CertificateFactory) Ensure() ([]CertUpdates, error) {
180180
if err != nil {
181181
return nil, err
182182
}
183+
admissionCA, err := loadOrCreateCA(cf.kluster, "Admission", &cf.store.AdmissionCACertificate, &cf.store.AdmissionCAPrivateKey, &certUpdates)
184+
if err != nil {
185+
return nil, err
186+
}
183187

184188
if err := ensureClientCertificate(
185189
etcdClientsCA,
@@ -277,6 +281,15 @@ func (cf *CertificateFactory) Ensure() ([]CertUpdates, error) {
277281
&certUpdates); err != nil {
278282
return nil, err
279283
}
284+
if err := ensureClientCertificate(
285+
admissionCA,
286+
"admission",
287+
nil,
288+
&cf.store.AdmissionCertificate,
289+
&cf.store.AdmissionPrivateKey,
290+
&certUpdates); err != nil {
291+
return nil, err
292+
}
280293

281294
apiServerDNSNames := []string{"kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local", "apiserver", cf.kluster.Name, fmt.Sprintf("%s.%s", cf.kluster.Name, cf.kluster.Namespace), fmt.Sprintf("%v.%v", cf.kluster.Name, cf.domain)}
282295
apiServerIPs := []net.IP{net.IPv4(127, 0, 0, 1), apiServiceIP, apiIP}

0 commit comments

Comments
 (0)