-
Notifications
You must be signed in to change notification settings - Fork 79
/
rotate-tls.go
228 lines (198 loc) · 9.06 KB
/
rotate-tls.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Authors of KubeArmor
// Package rotatetls rotates webhook controller tls certificates
package rotatetls
import (
"context"
"fmt"
"strings"
"time"
deployments "github.com/kubearmor/KubeArmor/deployments/get"
"github.com/kubearmor/kubearmor-client/install"
"github.com/kubearmor/kubearmor-client/k8s"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
)
// RotateTLS - rotate TLS certs
func RotateTLS(c *k8s.Client, namespace string) error {
// verify if all needed component are present in the cluster
fmt.Print("Checking if all needed component are present ...\n")
if _, err := c.K8sClientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.Background(), deployments.KubeArmorControllerWebhookServiceName, metav1.GetOptions{}); err != nil {
return err
}
if _, err := c.K8sClientset.CoreV1().Services(namespace).Get(context.Background(), deployments.KubeArmorControllerWebhookServiceName, metav1.GetOptions{}); err != nil {
return err
}
origdeploy, err := c.K8sClientset.AppsV1().Deployments(namespace).Get(context.Background(), deployments.KubeArmorControllerDeploymentName, metav1.GetOptions{})
if err != nil {
return err
}
if _, err := c.K8sClientset.CoreV1().Secrets(namespace).Get(context.Background(), deployments.KubeArmorControllerSecretName, metav1.GetOptions{}); err != nil {
return nil
}
fmt.Print("All needed component are present ...\n")
fmt.Print("Generating temporary certificates ...\n")
suffix, err := getFreeRandSuffix(c, namespace)
if err != nil {
fmt.Print("Error generating random suffix ...\n")
return err
}
fmt.Print("Using suffix " + suffix + " for all new temorary resources ...\n")
serviceName := deployments.KubeArmorControllerWebhookServiceName + "-" + suffix
caCert, tlsCrt, tlsKey, err := install.GeneratePki(namespace, serviceName)
if err != nil {
fmt.Print("Could'nt generate TLS secret ...\n")
return err
}
fmt.Print("Installing temporary resources ...\n")
fmt.Print("KubeArmor Controller temporary TLS certificates ...\n")
secret := deployments.GetKubeArmorControllerTLSSecret(namespace, caCert.String(), tlsCrt.String(), tlsKey.String())
secret.Name = secret.GetName() + "-" + suffix
if _, err := c.K8sClientset.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}); err != nil {
fmt.Print("KubeArmor Controller TLS certificates with the same suffix exists ...\n")
return err
}
fmt.Print("KubeArmor Controller temporary Deployment ...\n")
deploy := deployments.GetKubeArmorControllerDeployment(namespace)
deploy.Name = deploy.GetName() + "-" + suffix
for i, s := range deploy.Spec.Template.Spec.Volumes {
if s.Name == "cert" {
s.Secret.SecretName = secret.GetName()
deploy.Spec.Template.Spec.Volumes[i] = s
break
}
}
selectLabels := deploy.Spec.Selector.MatchLabels
selectLabels["kubearmor-app"] = suffix
deploy.Spec.Selector.MatchLabels = selectLabels
deploy.Spec.Replicas = origdeploy.Spec.Replicas
if _, err := c.K8sClientset.AppsV1().Deployments(namespace).Create(context.Background(), deploy, metav1.CreateOptions{}); err != nil {
fmt.Print("KubeArmor Controller Deployment with the same suffix exists ...\n")
return err
}
fmt.Print("Waiting for the deployment to start, sleeping 15 seconds ...\n")
time.Sleep(15 * time.Second)
fmt.Print("KubeArmor Controller temporary Service ...\n")
service := deployments.GetKubeArmorControllerWebhookService(namespace)
service.Name = serviceName
service.Spec.Selector = selectLabels
if _, err := c.K8sClientset.CoreV1().Services(namespace).Create(context.Background(), service, metav1.CreateOptions{}); err != nil {
fmt.Print("KubeArmor Controller Service with the same suffix exists ...\n")
return err
}
fmt.Print("KubeArmor Controller temporary Mutation Admission Registration ...\n")
mutation := deployments.GetKubeArmorControllerMutationAdmissionConfiguration(namespace, caCert.Bytes())
mutation.Name = mutation.Name + "-" + suffix
mutation.Webhooks[0].ClientConfig.Service.Name = service.GetName()
if _, err := c.K8sClientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.Background(), mutation, metav1.CreateOptions{}); err != nil {
fmt.Print("KubeArmor Controller Mutation Admission Registration with the same suffix exists ...\n")
return err
}
fmt.Print("Temporarily removing the main mutation registation ...\n")
if err := c.K8sClientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(context.Background(), deployments.KubeArmorControllerWebhookServiceName, metav1.DeleteOptions{}); err != nil {
return err
}
fmt.Print("Generating new certificates ...\n")
caCert, tlsCrt, tlsKey, err = install.GeneratePki(namespace, deployments.KubeArmorControllerWebhookServiceName)
if err != nil {
fmt.Print("Could'nt generate TLS secret ...\n")
return err
}
fmt.Print("Updating the main TLS secret ...\n")
if _, err := c.K8sClientset.CoreV1().Secrets(namespace).Update(context.Background(), deployments.GetKubeArmorControllerTLSSecret(namespace, caCert.String(), tlsCrt.String(), tlsKey.String()), metav1.UpdateOptions{}); err != nil {
return err
}
fmt.Print("Refreshing controller deployment ...\n")
replicas := int32(0)
origdeploy.Spec.Replicas = &replicas
if _, err := c.K8sClientset.AppsV1().Deployments(namespace).Update(context.Background(), origdeploy, metav1.UpdateOptions{}); err != nil {
return err
}
time.Sleep(10 * time.Second)
origdeploy, err = c.K8sClientset.AppsV1().Deployments(namespace).Get(context.Background(), deployments.KubeArmorControllerDeploymentName, metav1.GetOptions{})
if err != nil {
return err
}
origdeploy.Spec.Replicas = deploy.Spec.Replicas
if _, err := c.K8sClientset.AppsV1().Deployments(namespace).Update(context.Background(), origdeploy, metav1.UpdateOptions{}); err != nil {
return err
}
time.Sleep(10 * time.Second)
fmt.Print("Restoring main mutation registation ... \n")
if _, err := c.K8sClientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.Background(), deployments.GetKubeArmorControllerMutationAdmissionConfiguration(namespace, caCert.Bytes()), metav1.CreateOptions{}); err != nil {
if !strings.Contains(err.Error(), "already exists") {
return err
}
fmt.Print("KubeArmor Controller Mutation Admission Registration already exists ...\n")
}
fmt.Print("Deleting temprary ressources ...\n")
fmt.Print("Mutation Admission Registration ...\n")
if err := c.K8sClientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(context.Background(), mutation.Name, metav1.DeleteOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return err
}
fmt.Print("Mutation Admission Registration not found ...\n")
}
fmt.Print("KubeArmor Controller Service ...\n")
if err := c.K8sClientset.CoreV1().Services(namespace).Delete(context.Background(), service.Name, metav1.DeleteOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return err
}
fmt.Print("KubeArmor Controller Service not found ...\n")
}
fmt.Print("KubeArmor Controller Deployment ...\n")
if err := c.K8sClientset.AppsV1().Deployments(namespace).Delete(context.Background(), deploy.Name, metav1.DeleteOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return err
}
fmt.Print("KubeArmor Controller Deployment not found ...\n")
}
fmt.Print("KubeArmor Controller TLS certificates ...\n")
if err := c.K8sClientset.CoreV1().Secrets(namespace).Delete(context.Background(), secret.Name, metav1.DeleteOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return err
}
fmt.Print("KubeArmor Controller TLS certificates not found ...\n")
}
fmt.Print("Certificates were rotated ...\n")
return nil
}
func getFreeRandSuffix(c *k8s.Client, namespace string) (suffix string, err error) {
var found bool
for {
suffix = rand.String(5)
found = false
if _, err = c.K8sClientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.Background(), deployments.KubeArmorControllerWebhookServiceName+"-"+suffix, metav1.GetOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return "", err
}
} else {
found = true
}
if _, err = c.K8sClientset.CoreV1().Services(namespace).Get(context.Background(), deployments.KubeArmorControllerWebhookServiceName+"-"+suffix, metav1.GetOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return "", err
}
} else {
found = true
}
if _, err = c.K8sClientset.AppsV1().Deployments(namespace).Get(context.Background(), deployments.KubeArmorControllerDeploymentName+"-"+suffix, metav1.GetOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return "", err
}
} else {
found = true
}
if _, err = c.K8sClientset.CoreV1().Secrets(namespace).Get(context.Background(), deployments.KubeArmorControllerSecretName+"-"+suffix, metav1.GetOptions{}); err != nil {
if !strings.Contains(err.Error(), "not found") {
return "", err
}
} else {
found = true
}
if !found {
break
}
}
return suffix, nil
}