Skip to content

Commit e27965f

Browse files
authored
Merge branch 'main' into release-2.5.0
2 parents 5a4de3e + 42498eb commit e27965f

File tree

2 files changed

+276
-15
lines changed

2 files changed

+276
-15
lines changed

percona/controller/pgcluster/controller.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,17 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R
287287
}
288288

289289
func (r *PGClusterReconciler) reconcileTLS(ctx context.Context, cr *v2.PerconaPGCluster) error {
290-
checkSecretProjection := func(p *corev1.SecretProjection, requiredPaths ...string) error {
290+
if err := r.validateTLS(ctx, cr); err != nil {
291+
return errors.Wrap(err, "validate TLS")
292+
}
293+
if err := r.reconcileOldCACert(ctx, cr); err != nil {
294+
return errors.Wrap(err, "reconcile old CA")
295+
}
296+
return nil
297+
}
298+
299+
func (r *PGClusterReconciler) validateTLS(ctx context.Context, cr *v2.PerconaPGCluster) error {
300+
validateSecretProjection := func(p *corev1.SecretProjection, requiredPaths ...string) error {
291301
if p == nil {
292302
return nil
293303
}
@@ -321,33 +331,28 @@ func (r *PGClusterReconciler) reconcileTLS(ctx context.Context, cr *v2.PerconaPG
321331
return nil
322332
}
323333

324-
if err := checkSecretProjection(cr.Spec.Secrets.CustomRootCATLSSecret, "root.crt", "root.key"); err != nil {
334+
if err := validateSecretProjection(cr.Spec.Secrets.CustomRootCATLSSecret, "root.crt", "root.key"); err != nil {
325335
return errors.Wrap(err, "failed to validate .spec.customRootCATLSSecret")
326336
}
327337

328338
certPaths := []string{"tls.key", "tls.crt"}
329339
if cr.Spec.Secrets.CustomRootCATLSSecret == nil {
330340
certPaths = append(certPaths, "ca.crt")
331341
}
332-
if err := checkSecretProjection(cr.Spec.Secrets.CustomTLSSecret, certPaths...); err != nil {
342+
if err := validateSecretProjection(cr.Spec.Secrets.CustomTLSSecret, certPaths...); err != nil {
333343
return errors.Wrap(err, "failed to validate .spec.customTLSSecret")
334344
}
335-
if err := checkSecretProjection(cr.Spec.Secrets.CustomReplicationClientTLSSecret, certPaths...); err != nil {
345+
if err := validateSecretProjection(cr.Spec.Secrets.CustomReplicationClientTLSSecret, certPaths...); err != nil {
336346
return errors.Wrap(err, "failed to validate .spec.customReplicationTLSSecret")
337347
}
348+
return nil
349+
}
338350

351+
func (r *PGClusterReconciler) reconcileOldCACert(ctx context.Context, cr *v2.PerconaPGCluster) error {
339352
if cr.Spec.Secrets.CustomRootCATLSSecret != nil {
340353
return nil
341354
}
342355

343-
if err := r.reconcileOldCACert(ctx, cr); err != nil {
344-
return errors.Wrap(err, "reconcile old CA")
345-
}
346-
347-
return nil
348-
}
349-
350-
func (r *PGClusterReconciler) reconcileOldCACert(ctx context.Context, cr *v2.PerconaPGCluster) error {
351356
oldCASecret := &corev1.Secret{
352357
ObjectMeta: metav1.ObjectMeta{
353358
Name: naming.RootCertSecret,

percona/controller/pgcluster/controller_test.go

Lines changed: 259 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ package pgcluster
55

66
import (
77
"context"
8-
// #nosec G501
9-
"crypto/md5"
8+
"crypto/md5" //nolint:gosec
109
"fmt"
10+
"strconv"
1111
"sync"
1212
"time"
1313

@@ -767,7 +767,6 @@ var _ = Describe("Users", Ordered, func() {
767767

768768
return errors.New("cluster not deleted")
769769
}, time.Second*15, time.Millisecond*250).Should(BeNil())
770-
771770
})
772771
})
773772

@@ -1284,3 +1283,260 @@ var _ = Describe("Operator-created sidecar container resources", Ordered, func()
12841283
}
12851284
})
12861285
})
1286+
1287+
var _ = Describe("Validate TLS", Ordered, func() {
1288+
ctx := context.Background()
1289+
1290+
const crName = "validate-tls"
1291+
const ns = crName
1292+
1293+
namespace := &corev1.Namespace{
1294+
ObjectMeta: metav1.ObjectMeta{
1295+
Name: crName,
1296+
Namespace: ns,
1297+
},
1298+
}
1299+
1300+
BeforeAll(func() {
1301+
By("Creating the Namespace to perform the tests")
1302+
err := k8sClient.Create(ctx, namespace)
1303+
Expect(err).To(Not(HaveOccurred()))
1304+
})
1305+
1306+
AfterAll(func() {
1307+
By("Deleting the Namespace to perform the tests")
1308+
_ = k8sClient.Delete(ctx, namespace)
1309+
})
1310+
1311+
cr, err := readDefaultCR(crName, ns)
1312+
It("should read default cr.yaml", func() {
1313+
Expect(err).NotTo(HaveOccurred())
1314+
})
1315+
1316+
cr.Default()
1317+
1318+
It("should create PerconaPGCluster", func() {
1319+
Expect(k8sClient.Create(ctx, cr)).Should(Succeed())
1320+
})
1321+
1322+
checkSecretProjection := func(cr *v2.PerconaPGCluster, projection *corev1.SecretProjection, secretName string, neededKeys []string) {
1323+
GinkgoHelper()
1324+
It("should fail if secret doesn't exist", func() {
1325+
projection.Name = secretName
1326+
1327+
err := reconciler(cr).validateTLS(ctx, cr)
1328+
Expect(err).To(HaveOccurred())
1329+
})
1330+
It("should fail if secret doesn't have needed data", func() {
1331+
secret := &corev1.Secret{
1332+
ObjectMeta: metav1.ObjectMeta{
1333+
Name: secretName,
1334+
Namespace: cr.Namespace,
1335+
},
1336+
}
1337+
Expect(k8sClient.Create(ctx, secret)).NotTo(HaveOccurred())
1338+
1339+
err := reconciler(cr).validateTLS(ctx, cr)
1340+
Expect(err).To(HaveOccurred())
1341+
})
1342+
1343+
It("should not fail if needed keys specified in the secret", func() {
1344+
secret := new(corev1.Secret)
1345+
Expect(k8sClient.Get(ctx, types.NamespacedName{
1346+
Name: secretName,
1347+
Namespace: cr.Namespace,
1348+
}, secret)).NotTo(HaveOccurred())
1349+
secret.Data = make(map[string][]byte)
1350+
for _, v := range neededKeys {
1351+
secret.Data[v] = []byte("some-data")
1352+
}
1353+
Expect(k8sClient.Update(ctx, secret)).NotTo(HaveOccurred())
1354+
1355+
err := reconciler(cr).validateTLS(ctx, cr)
1356+
Expect(err).NotTo(HaveOccurred())
1357+
})
1358+
1359+
It("should not fail if wrong items.path are specified but needed key exist in secrets", func() {
1360+
projection.Items = []corev1.KeyToPath{}
1361+
for i, v := range neededKeys {
1362+
projection.Items = append(projection.Items, corev1.KeyToPath{
1363+
Key: v,
1364+
Path: "wrong-path" + "-" + strconv.Itoa(i),
1365+
})
1366+
}
1367+
1368+
err := reconciler(cr).validateTLS(ctx, cr)
1369+
Expect(err).NotTo(HaveOccurred())
1370+
})
1371+
1372+
It("should fail if items.key are specified which don't exist in the secret", func() {
1373+
projection.Items = []corev1.KeyToPath{}
1374+
for i, v := range neededKeys {
1375+
projection.Items = append(projection.Items, corev1.KeyToPath{
1376+
Key: "non-existent-key" + strconv.Itoa(i),
1377+
Path: v,
1378+
})
1379+
}
1380+
err := reconciler(cr).validateTLS(ctx, cr)
1381+
Expect(err).To(HaveOccurred())
1382+
})
1383+
1384+
It("should not fail if wrong items.path are specified but needed key exist in secrets", func() {
1385+
projection.Items = []corev1.KeyToPath{}
1386+
for _, v := range neededKeys {
1387+
projection.Items = append(projection.Items, corev1.KeyToPath{
1388+
Key: v,
1389+
Path: v + "-wrong",
1390+
})
1391+
}
1392+
1393+
err := reconciler(cr).validateTLS(ctx, cr)
1394+
Expect(err).NotTo(HaveOccurred())
1395+
})
1396+
1397+
It("should not fail with custom data keys in the secret", func() {
1398+
secret := new(corev1.Secret)
1399+
Expect(k8sClient.Get(ctx, types.NamespacedName{
1400+
Name: secretName,
1401+
Namespace: cr.Namespace,
1402+
}, secret)).NotTo(HaveOccurred())
1403+
1404+
secret.Data = map[string][]byte{}
1405+
for _, v := range neededKeys {
1406+
secret.Data[v+"-custom"] = []byte("some-data")
1407+
}
1408+
Expect(k8sClient.Update(ctx, secret)).NotTo(HaveOccurred())
1409+
projection.Items = []corev1.KeyToPath{}
1410+
for _, v := range neededKeys {
1411+
projection.Items = append(projection.Items, corev1.KeyToPath{
1412+
Key: v + "-custom",
1413+
Path: v,
1414+
})
1415+
}
1416+
1417+
err := reconciler(cr).validateTLS(ctx, cr)
1418+
Expect(err).NotTo(HaveOccurred())
1419+
})
1420+
1421+
It("should fail if items.key are specified but not paths", func() {
1422+
projection.Items = []corev1.KeyToPath{}
1423+
for _, v := range neededKeys {
1424+
projection.Items = append(projection.Items, corev1.KeyToPath{
1425+
Key: v,
1426+
})
1427+
}
1428+
1429+
err := reconciler(cr).validateTLS(ctx, cr)
1430+
Expect(err).To(HaveOccurred())
1431+
})
1432+
}
1433+
1434+
Context("checking validation", func() {
1435+
Describe("should check validation for cr.Spec.Secrets.CustomRootCATLSSecret", func() {
1436+
cr := cr.DeepCopy()
1437+
neededKeys := []string{
1438+
"root.crt",
1439+
"root.key",
1440+
}
1441+
cr.Spec.Secrets.CustomRootCATLSSecret = new(corev1.SecretProjection)
1442+
checkSecretProjection(cr, cr.Spec.Secrets.CustomRootCATLSSecret, "root-ca", neededKeys)
1443+
It("should not fail if the section was not specified", func() {
1444+
cr.Spec.Secrets.CustomRootCATLSSecret = nil
1445+
err := reconciler(cr).validateTLS(ctx, cr)
1446+
Expect(err).NotTo(HaveOccurred())
1447+
})
1448+
})
1449+
Describe("should check validation for cr.Spec.Secrets.CustomTLSSecret", func() {
1450+
cr := cr.DeepCopy()
1451+
neededKeys := []string{
1452+
"ca.crt",
1453+
"tls.crt",
1454+
"tls.key",
1455+
}
1456+
cr.Spec.Secrets.CustomTLSSecret = new(corev1.SecretProjection)
1457+
checkSecretProjection(cr, cr.Spec.Secrets.CustomTLSSecret, "tls-secret", neededKeys)
1458+
It("should not fail if the section was not specified", func() {
1459+
cr.Spec.Secrets.CustomTLSSecret = nil
1460+
err := reconciler(cr).validateTLS(ctx, cr)
1461+
Expect(err).NotTo(HaveOccurred())
1462+
})
1463+
})
1464+
Describe("should check validation for cr.Spec.Secrets.CustomReplicationClientTLSSecret", func() {
1465+
cr := cr.DeepCopy()
1466+
neededKeys := []string{
1467+
"ca.crt",
1468+
"tls.crt",
1469+
"tls.key",
1470+
}
1471+
cr.Spec.Secrets.CustomReplicationClientTLSSecret = new(corev1.SecretProjection)
1472+
checkSecretProjection(cr, cr.Spec.Secrets.CustomReplicationClientTLSSecret, "repl-tls-secret", neededKeys)
1473+
It("should not fail if the section was not specified", func() {
1474+
cr.Spec.Secrets.CustomReplicationClientTLSSecret = nil
1475+
err := reconciler(cr).validateTLS(ctx, cr)
1476+
Expect(err).NotTo(HaveOccurred())
1477+
})
1478+
})
1479+
})
1480+
1481+
checkSecretProjectionWithCA := func(cr *v2.PerconaPGCluster, projection *corev1.SecretProjection, secretName string) {
1482+
GinkgoHelper()
1483+
neededKeys := []string{
1484+
"tls.crt",
1485+
"tls.key",
1486+
}
1487+
projection.Name = secretName
1488+
It("should create secret", func() {
1489+
secret := &corev1.Secret{
1490+
ObjectMeta: metav1.ObjectMeta{
1491+
Name: secretName,
1492+
Namespace: cr.Namespace,
1493+
},
1494+
}
1495+
secret.Data = map[string][]byte{}
1496+
for _, v := range neededKeys {
1497+
secret.Data[v] = []byte("some-data")
1498+
}
1499+
Expect(k8sClient.Create(ctx, secret)).NotTo(HaveOccurred())
1500+
})
1501+
It("should fail when CA is not specified", func() {
1502+
err := reconciler(cr).validateTLS(ctx, cr)
1503+
Expect(err).To(HaveOccurred())
1504+
})
1505+
It("should not fail when CA is specified", func() {
1506+
secretName := secretName + "-ca"
1507+
neededKeys := []string{
1508+
"root.crt",
1509+
"root.key",
1510+
}
1511+
cr.Spec.Secrets.CustomRootCATLSSecret = new(corev1.SecretProjection)
1512+
projection := cr.Spec.Secrets.CustomRootCATLSSecret
1513+
projection.Name = secretName
1514+
secret := &corev1.Secret{
1515+
ObjectMeta: metav1.ObjectMeta{
1516+
Name: secretName,
1517+
Namespace: cr.Namespace,
1518+
},
1519+
}
1520+
secret.Data = make(map[string][]byte)
1521+
for _, v := range neededKeys {
1522+
secret.Data[v] = []byte("some-data")
1523+
}
1524+
Expect(k8sClient.Create(ctx, secret)).NotTo(HaveOccurred())
1525+
1526+
err := reconciler(cr).validateTLS(ctx, cr)
1527+
Expect(err).NotTo(HaveOccurred())
1528+
})
1529+
}
1530+
Context("check validation for cr.Spec.Secrets.CustomTLSSecret when cr.Spec.Secrets.CustomRootCATLSSecret is specified", func() {
1531+
cr := cr.DeepCopy()
1532+
secretName := "custom-tls-secret-with-ca" //nolint:gosec
1533+
cr.Spec.Secrets.CustomTLSSecret = new(corev1.SecretProjection)
1534+
checkSecretProjectionWithCA(cr, cr.Spec.Secrets.CustomTLSSecret, secretName)
1535+
})
1536+
Context("should check validation for cr.Spec.Secrets.CustomReplicationClientTLSSecret when cr.Spec.Secrets.CustomRootCATLSSecret is specified", func() {
1537+
cr := cr.DeepCopy()
1538+
secretName := "custom-replication-tls-secret-with-ca" //nolint:gosec
1539+
cr.Spec.Secrets.CustomReplicationClientTLSSecret = new(corev1.SecretProjection)
1540+
checkSecretProjectionWithCA(cr, cr.Spec.Secrets.CustomReplicationClientTLSSecret, secretName)
1541+
})
1542+
})

0 commit comments

Comments
 (0)